aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.common4
-rw-r--r--Makefile.doc3
-rw-r--r--azure-pipelines.yml37
-rw-r--r--checker/values.ml2
-rw-r--r--coqpp/coqpp_main.ml2
-rwxr-xr-xdev/ci/ci-iris.sh4
-rw-r--r--dev/ci/user-overlays/12218-proux01-numeral-notations-non-inductive.sh18
-rw-r--r--dev/ci/user-overlays/13139-ppedrot-clean-hint-constr.sh9
-rw-r--r--dev/doc/changes.md7
-rw-r--r--dev/doc/critical-bugs12
-rw-r--r--dev/doc/shield-icon.pngbin2512 -> 8582 bytes
-rw-r--r--doc/changelog/01-kernel/12738-fix-sr-cumul-inds.rst5
-rw-r--r--doc/changelog/01-kernel/13356-primarray-cumul.rst5
-rw-r--r--doc/changelog/02-specification-language/13183-using-att.rst6
-rw-r--r--doc/changelog/02-specification-language/13217-master+fix13216-typeclass-for-match-return-clause.rst5
-rw-r--r--doc/changelog/03-notations/12099-master+constraining-terms-occurring-also-as-pattern-in-notations.rst4
-rw-r--r--doc/changelog/03-notations/12218-numeral-notations-non-inductive.rst19
-rw-r--r--doc/changelog/03-notations/12946-master+fix12908-part1-collision-lonely-notation-printing.rst6
-rw-r--r--doc/changelog/03-notations/13026-master+fix-printing-custom-no-level-8.2.rst7
-rw-r--r--doc/changelog/03-notations/13067-master+fix-display-parentheses-default-coqide.rst5
-rw-r--r--doc/changelog/03-notations/13092-master+fix-13078-no-binder-in-pattern-notation.rst5
-rw-r--r--doc/changelog/04-tactics/12816-master+fix12787-K-redex-injection-anomaly.rst6
-rw-r--r--doc/changelog/04-tactics/12847-master+inversion-works-with-eq-in-type.rst6
-rw-r--r--doc/changelog/05-tactic-language/13232-ltac2-if-then-else.rst5
-rw-r--r--doc/changelog/06-ssreflect/12857-changelog-for-12857.rst8
-rw-r--r--doc/changelog/06-ssreflect/13317-ssr_dup_swap_apply_ipat.rst4
-rw-r--r--doc/changelog/07-commands-and-options/13139-clean-hint-constr.rst6
-rw-r--r--doc/changelog/07-commands-and-options/13255-master+fix13244-use-coercions-in-search.rst7
-rw-r--r--doc/changelog/07-commands-and-options/13339-proof-using-noinit.rst5
-rw-r--r--doc/changelog/07-commands-and-options/13345-master+doc-add-ml-path-not-exported.rst5
-rw-r--r--doc/changelog/08-tools/12754-master+fix-coqdoc-index-escaping.rst6
-rw-r--r--doc/changelog/08-tools/12772-fix-details.rst5
-rw-r--r--doc/changelog/08-tools/13063-fix-no-output-sync-make-file.rst6
-rw-r--r--doc/changelog/09-coqide/00000-title.rst2
-rw-r--r--doc/changelog/09-coqide/13145-master+coqide-printing-goal-names-support.rst4
-rw-r--r--doc/changelog/10-standard-library/12420-decidable.rst4
-rw-r--r--doc/changelog/11-infrastructure-and-dependencies/12864-fix-approve-output.rst5
-rw-r--r--doc/changelog/11-infrastructure-and-dependencies/12972-ocaml+4_11.rst4
-rw-r--r--doc/changelog/11-infrastructure-and-dependencies/13011-sphinx-3.rst5
-rw-r--r--doc/sphinx/README.rst2
-rw-r--r--doc/sphinx/README.template.rst2
-rw-r--r--doc/sphinx/addendum/extraction.rst108
-rw-r--r--doc/sphinx/addendum/generalized-rewriting.rst6
-rw-r--r--doc/sphinx/addendum/implicit-coercions.rst2
-rw-r--r--doc/sphinx/addendum/micromega.rst4
-rw-r--r--doc/sphinx/addendum/miscellaneous-extensions.rst2
-rw-r--r--doc/sphinx/addendum/nsatz.rst2
-rw-r--r--doc/sphinx/addendum/omega.rst6
-rw-r--r--doc/sphinx/addendum/parallel-proof-processing.rst46
-rw-r--r--doc/sphinx/addendum/program.rst28
-rw-r--r--doc/sphinx/addendum/ring.rst37
-rw-r--r--doc/sphinx/addendum/sprop.rst4
-rw-r--r--doc/sphinx/addendum/type-classes.rst21
-rw-r--r--doc/sphinx/addendum/universe-polymorphism.rst6
-rw-r--r--doc/sphinx/appendix/history-and-changes/index.rst6
-rw-r--r--doc/sphinx/changes.rst712
-rw-r--r--doc/sphinx/history.rst82
-rw-r--r--doc/sphinx/introduction.rst30
-rw-r--r--doc/sphinx/language/cic.rst14
-rw-r--r--doc/sphinx/language/coq-library.rst18
-rw-r--r--doc/sphinx/language/core/assumptions.rst2
-rw-r--r--doc/sphinx/language/core/basic.rst54
-rw-r--r--doc/sphinx/language/core/coinductive.rst10
-rw-r--r--doc/sphinx/language/core/conversion.rst2
-rw-r--r--doc/sphinx/language/core/definitions.rst31
-rw-r--r--doc/sphinx/language/core/index.rst2
-rw-r--r--doc/sphinx/language/core/inductive.rst20
-rw-r--r--doc/sphinx/language/core/modules.rst40
-rw-r--r--doc/sphinx/language/core/primitive.rst28
-rw-r--r--doc/sphinx/language/core/sections.rst2
-rw-r--r--doc/sphinx/language/extensions/arguments-command.rst11
-rw-r--r--doc/sphinx/language/extensions/canonical.rst24
-rw-r--r--doc/sphinx/language/extensions/evars.rst4
-rw-r--r--doc/sphinx/language/extensions/implicit-arguments.rst12
-rw-r--r--doc/sphinx/language/extensions/index.rst2
-rw-r--r--doc/sphinx/language/extensions/match.rst23
-rw-r--r--doc/sphinx/practical-tools/coq-commands.rst96
-rw-r--r--doc/sphinx/practical-tools/coqide.rst60
-rw-r--r--doc/sphinx/practical-tools/utilities.rst92
-rw-r--r--doc/sphinx/proof-engine/ltac.rst44
-rw-r--r--doc/sphinx/proof-engine/ltac2.rst104
-rw-r--r--doc/sphinx/proof-engine/proof-handling.rst902
-rw-r--r--doc/sphinx/proof-engine/ssreflect-proof-language.rst95
-rw-r--r--doc/sphinx/proof-engine/tactics.rst1965
-rw-r--r--doc/sphinx/proof-engine/vernacular-commands.rst129
-rw-r--r--doc/sphinx/proofs/automatic-tactics/auto.rst672
-rw-r--r--doc/sphinx/proofs/automatic-tactics/index.rst10
-rw-r--r--doc/sphinx/proofs/automatic-tactics/logic.rst228
-rw-r--r--doc/sphinx/proofs/creating-tactics/index.rst10
-rw-r--r--doc/sphinx/proofs/writing-proofs/index.rst11
-rw-r--r--doc/sphinx/proofs/writing-proofs/proof-mode.rst1037
-rw-r--r--doc/sphinx/proofs/writing-proofs/rewriting.rst857
-rw-r--r--doc/sphinx/refman-preamble.rst6
-rw-r--r--doc/sphinx/user-extensions/proof-schemes.rst2
-rw-r--r--doc/sphinx/user-extensions/syntax-extensions.rst450
-rw-r--r--doc/sphinx/using/libraries/index.rst6
-rw-r--r--doc/sphinx/using/libraries/writing.rst8
-rw-r--r--doc/sphinx/using/tools/coqdoc.rst48
-rw-r--r--doc/sphinx/using/tools/index.rst8
-rw-r--r--doc/stdlib/hidden-files1
-rw-r--r--doc/stdlib/index-list.html.template5
-rw-r--r--doc/tools/coqrst/notations/TacticNotations.g3
-rw-r--r--doc/tools/coqrst/notations/TacticNotationsLexer.py59
-rw-r--r--doc/tools/docgram/README.md2
-rw-r--r--doc/tools/docgram/common.edit_mlg761
-rw-r--r--doc/tools/docgram/doc_grammar.ml72
-rw-r--r--doc/tools/docgram/dune6
-rw-r--r--doc/tools/docgram/fullGrammar751
-rw-r--r--doc/tools/docgram/orderedGrammar396
-rw-r--r--engine/eConstr.ml9
-rw-r--r--engine/eConstr.mli1
-rw-r--r--engine/evarutil.ml3
-rw-r--r--engine/evd.ml4
-rw-r--r--engine/evd.mli12
-rw-r--r--engine/uState.ml278
-rw-r--r--engine/uState.mli33
-rw-r--r--ide/coqide/coq.ml4
-rw-r--r--ide/coqide/coqide_ui.ml1
-rw-r--r--ide/coqide/idetop.ml4
-rw-r--r--ide/coqide/wg_ProofView.ml28
-rw-r--r--interp/constrexpr.ml2
-rw-r--r--interp/constrexpr_ops.ml40
-rw-r--r--interp/constrexpr_ops.mli7
-rw-r--r--interp/constrextern.ml10
-rw-r--r--interp/constrintern.ml269
-rw-r--r--interp/constrintern.mli13
-rw-r--r--interp/dumpglob.ml32
-rw-r--r--interp/dumpglob.mli12
-rw-r--r--interp/implicit_quantifiers.ml4
-rw-r--r--interp/modintern.ml2
-rw-r--r--interp/notation.ml294
-rw-r--r--interp/notation.mli44
-rw-r--r--interp/notation_ops.ml17
-rw-r--r--interp/numTok.mli30
-rw-r--r--interp/smartlocate.ml38
-rw-r--r--interp/smartlocate.mli12
-rw-r--r--interp/syntax_def.ml6
-rw-r--r--interp/syntax_def.mli2
-rw-r--r--kernel/cClosure.ml29
-rw-r--r--kernel/environ.ml12
-rw-r--r--kernel/environ.mli7
-rw-r--r--kernel/names.ml4
-rw-r--r--kernel/names.mli3
-rw-r--r--kernel/nativecode.ml83
-rw-r--r--kernel/nativecode.mli3
-rw-r--r--kernel/nativeconv.ml2
-rw-r--r--kernel/nativelambda.ml2
-rw-r--r--kernel/nativelib.ml43
-rw-r--r--kernel/nativelib.mli13
-rw-r--r--kernel/reduction.ml88
-rw-r--r--kernel/safe_typing.ml21
-rw-r--r--kernel/safe_typing.mli4
-rw-r--r--kernel/vars.ml3
-rw-r--r--lib/control.ml10
-rw-r--r--library/global.mli2
-rw-r--r--parsing/cLexer.ml8
-rw-r--r--parsing/cLexer.mli4
-rw-r--r--parsing/g_constr.mlg16
-rw-r--r--plugins/firstorder/g_ground.mlg11
-rw-r--r--plugins/funind/indfun_common.ml4
-rw-r--r--plugins/ltac/g_ltac.mlg10
-rw-r--r--plugins/ltac/g_rewrite.mlg21
-rw-r--r--plugins/ltac/g_tactic.mlg6
-rw-r--r--plugins/ltac/pptactic.ml2
-rw-r--r--plugins/ltac/rewrite.ml16
-rw-r--r--plugins/ltac/rewrite.mli2
-rw-r--r--plugins/ltac/taccoerce.ml9
-rw-r--r--plugins/ltac/tacentries.ml51
-rw-r--r--plugins/ltac/tacentries.mli3
-rw-r--r--plugins/ltac/tacintern.ml32
-rw-r--r--plugins/ltac/tacintern.mli3
-rw-r--r--plugins/ltac/tacinterp.ml21
-rw-r--r--plugins/ltac/tacinterp.mli3
-rw-r--r--plugins/ssr/ssrparser.mlg2
-rw-r--r--plugins/ssr/ssrvernac.mlg16
-rw-r--r--plugins/ssr/ssrvernac.mli2
-rw-r--r--plugins/ssrsearch/g_search.mlg4
-rw-r--r--plugins/syntax/dune24
-rw-r--r--plugins/syntax/g_number_string.mlg110
-rw-r--r--plugins/syntax/g_numeral.mlg51
-rw-r--r--plugins/syntax/g_string.mlg25
-rw-r--r--plugins/syntax/int63_syntax.ml3
-rw-r--r--plugins/syntax/number.ml505
-rw-r--r--plugins/syntax/number.mli31
-rw-r--r--plugins/syntax/number_string_notation_plugin.mlpack3
-rw-r--r--plugins/syntax/numeral.ml217
-rw-r--r--plugins/syntax/numeral.mli19
-rw-r--r--plugins/syntax/numeral_notation_plugin.mlpack2
-rw-r--r--plugins/syntax/r_syntax.ml214
-rw-r--r--plugins/syntax/r_syntax.mli9
-rw-r--r--plugins/syntax/r_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/string_notation.ml27
-rw-r--r--plugins/syntax/string_notation.mli4
-rw-r--r--plugins/syntax/string_notation_plugin.mlpack2
-rw-r--r--pretyping/cases.ml2
-rw-r--r--pretyping/evarconv.ml9
-rw-r--r--pretyping/glob_ops.ml1
-rw-r--r--pretyping/nativenorm.ml2
-rw-r--r--pretyping/pretyping.ml16
-rw-r--r--pretyping/unification.ml13
-rw-r--r--printing/ppconstr.ml17
-rw-r--r--printing/printer.ml2
-rw-r--r--printing/printer.mli3
-rw-r--r--stm/stm.ml5
-rw-r--r--tactics/class_tactics.ml3
-rw-r--r--tactics/hints.ml9
-rw-r--r--tactics/hints.mli13
-rw-r--r--tactics/ind_tables.ml6
-rw-r--r--test-suite/Makefile3
-rw-r--r--test-suite/bugs/closed/bug_10972.v9
-rw-r--r--test-suite/bugs/closed/bug_13078.v10
-rw-r--r--test-suite/bugs/closed/bug_13131.v6
-rw-r--r--test-suite/bugs/closed/bug_13162.v7
-rw-r--r--test-suite/bugs/closed/bug_13178.v3
-rw-r--r--test-suite/bugs/closed/bug_13216.v4
-rw-r--r--test-suite/bugs/closed/bug_13276.v9
-rw-r--r--test-suite/bugs/closed/bug_13330.v17
-rw-r--r--test-suite/bugs/closed/bug_13348.v10
-rw-r--r--test-suite/bugs/closed/bug_13354.v10
-rw-r--r--test-suite/bugs/opened/bug_3395.v232
-rwxr-xr-xtest-suite/misc/13330.sh10
-rw-r--r--test-suite/misc/13330/bug_13330.v16
-rw-r--r--test-suite/output/ErrorLocation_13241_1.out3
-rw-r--r--test-suite/output/ErrorLocation_13241_1.v5
-rw-r--r--test-suite/output/ErrorLocation_13241_2.out3
-rw-r--r--test-suite/output/ErrorLocation_13241_2.v5
-rw-r--r--test-suite/output/Notations4.out54
-rw-r--r--test-suite/output/Notations4.v105
-rw-r--r--test-suite/output/NumberNotations.out291
-rw-r--r--test-suite/output/NumberNotations.v579
-rw-r--r--test-suite/output/QArithSyntax.out90
-rw-r--r--test-suite/output/QArithSyntax.v34
-rw-r--r--test-suite/output/RealSyntax.out101
-rw-r--r--test-suite/output/RealSyntax.v44
-rw-r--r--test-suite/output/Search.out112
-rw-r--r--test-suite/output/Search.v13
-rw-r--r--test-suite/output/SearchHead.out6
-rw-r--r--test-suite/output/SearchPattern.out8
-rw-r--r--test-suite/output/Search_bug13298.out1
-rw-r--r--test-suite/output/Search_bug13298.v3
-rw-r--r--test-suite/output/StringSyntax.out22
-rw-r--r--test-suite/output/StringSyntax.v65
-rw-r--r--test-suite/output/ZSyntax.v2
-rw-r--r--test-suite/output/bug_12159.v6
-rw-r--r--test-suite/output/bug_13004.out4
-rw-r--r--test-suite/output/bug_13238.out8
-rw-r--r--test-suite/output/bug_13244.out9
-rw-r--r--test-suite/output/bug_13244.v3
-rw-r--r--test-suite/output/bug_13320.out2
-rw-r--r--test-suite/output/bug_13320.v2
-rw-r--r--test-suite/output/prim_array.out9
-rw-r--r--test-suite/output/prim_array.v10
-rwxr-xr-xtest-suite/report.sh2
-rw-r--r--test-suite/ssr/ipat_apply.v13
-rw-r--r--test-suite/ssr/ipat_dup.v13
-rw-r--r--test-suite/ssr/ipat_swap.v13
-rw-r--r--test-suite/success/CompatOldOldFlag.v6
-rw-r--r--test-suite/success/NumberNotationsNoLocal.v (renamed from test-suite/success/NumeralNotationsNoLocal.v)2
-rw-r--r--test-suite/success/definition_using.v68
-rw-r--r--test-suite/success/proof_using_noinit.v9
-rw-r--r--test-suite/success/rewrite_strat.v9
-rw-r--r--test-suite/success/sprop_uip.v27
-rwxr-xr-xtest-suite/tools/update-compat/run.sh2
-rw-r--r--theories/Arith/Div2.v10
-rw-r--r--theories/Arith/Euclid.v6
-rw-r--r--theories/Arith/Even.v14
-rw-r--r--theories/Bool/Sumbool.v6
-rw-r--r--theories/Classes/DecidableClass.v10
-rw-r--r--theories/Compat/Coq810.v13
-rw-r--r--theories/Init/Byte.v2
-rw-r--r--theories/Init/Decimal.v6
-rw-r--r--theories/Init/Hexadecimal.v38
-rw-r--r--theories/Init/Nat.v20
-rw-r--r--theories/Init/Number.v45
-rw-r--r--theories/Init/Numeral.v67
-rw-r--r--theories/Init/Prelude.v15
-rw-r--r--theories/NArith/BinNatDef.v16
-rw-r--r--theories/NArith/Ndigits.v119
-rw-r--r--theories/Numbers/AltBinNotations.v2
-rw-r--r--theories/Numbers/DecimalFacts.v607
-rw-r--r--theories/Numbers/DecimalN.v4
-rw-r--r--theories/Numbers/DecimalNat.v4
-rw-r--r--theories/Numbers/DecimalQ.v894
-rw-r--r--theories/Numbers/DecimalR.v312
-rw-r--r--theories/Numbers/DecimalZ.v27
-rw-r--r--theories/Numbers/HexadecimalFacts.v627
-rw-r--r--theories/Numbers/HexadecimalN.v4
-rw-r--r--theories/Numbers/HexadecimalNat.v4
-rw-r--r--theories/Numbers/HexadecimalQ.v880
-rw-r--r--theories/Numbers/HexadecimalR.v302
-rw-r--r--theories/Numbers/HexadecimalZ.v27
-rw-r--r--theories/Numbers/Integer/Abstract/ZAdd.v173
-rw-r--r--theories/Numbers/Integer/Abstract/ZAddOrder.v8
-rw-r--r--theories/Numbers/Integer/Abstract/ZBits.v63
-rw-r--r--theories/Numbers/Integer/Abstract/ZDivFloor.v64
-rw-r--r--theories/Numbers/Integer/Abstract/ZDivTrunc.v66
-rw-r--r--theories/Numbers/Integer/Abstract/ZGcd.v12
-rw-r--r--theories/Numbers/Integer/Abstract/ZLcm.v12
-rw-r--r--theories/Numbers/Integer/Abstract/ZMaxMin.v72
-rw-r--r--theories/Numbers/Integer/Abstract/ZMulOrder.v4
-rw-r--r--theories/Numbers/Integer/Abstract/ZParity.v6
-rw-r--r--theories/Numbers/Integer/Abstract/ZPow.v4
-rw-r--r--theories/Numbers/Integer/Abstract/ZSgnAbs.v46
-rw-r--r--theories/PArith/BinPosDef.v16
-rw-r--r--theories/QArith/QArith_base.v285
-rw-r--r--theories/QArith/Qreals.v2
-rw-r--r--theories/Reals/Rdefinitions.v167
-rw-r--r--theories/Reals/Rregisternames.v4
-rw-r--r--theories/Strings/Ascii.v10
-rw-r--r--theories/Strings/String.v7
-rw-r--r--theories/Vectors/Fin.v15
-rw-r--r--theories/Vectors/VectorDef.v2
-rw-r--r--theories/Vectors/VectorEq.v2
-rw-r--r--theories/Vectors/VectorSpec.v88
-rw-r--r--theories/ZArith/BinInt.v26
-rw-r--r--theories/ZArith/BinIntDef.v14
-rw-r--r--theories/ZArith/Wf_Z.v16
-rw-r--r--theories/ZArith/ZArith_dec.v12
-rw-r--r--theories/ZArith/Zabs.v4
-rw-r--r--theories/ZArith/Zcomplements.v17
-rw-r--r--theories/ZArith/Zdiv.v71
-rw-r--r--theories/ZArith/Znat.v4
-rw-r--r--theories/ZArith/Znumtheory.v77
-rw-r--r--theories/ZArith/Zorder.v2
-rw-r--r--theories/ZArith/Zpow_def.v6
-rw-r--r--theories/dune4
-rw-r--r--theories/micromega/EnvRing.v60
-rw-r--r--theories/micromega/OrderedRing.v4
-rw-r--r--theories/micromega/Refl.v26
-rw-r--r--theories/micromega/RingMicromega.v97
-rw-r--r--theories/micromega/Tauto.v215
-rw-r--r--theories/micromega/ZCoeff.v2
-rw-r--r--theories/micromega/ZifyClasses.v2
-rw-r--r--theories/micromega/ZifyInst.v8
-rw-r--r--theories/micromega/Ztac.v8
-rw-r--r--theories/setoid_ring/InitialRing.v43
-rw-r--r--theories/setoid_ring/Ring.v16
-rw-r--r--theories/setoid_ring/Ring_polynom.v106
-rw-r--r--theories/ssr/ssreflect.v56
-rw-r--r--theories/ssrmatching/ssrmatching.v2
-rw-r--r--toplevel/ccompile.ml2
-rw-r--r--toplevel/coqargs.ml3
-rw-r--r--user-contrib/Ltac2/g_ltac2.mlg2
-rw-r--r--user-contrib/Ltac2/tac2expr.mli1
-rw-r--r--user-contrib/Ltac2/tac2intern.ml20
-rw-r--r--vernac/attributes.ml8
-rw-r--r--vernac/attributes.mli1
-rw-r--r--vernac/classes.ml4
-rw-r--r--vernac/comAssumption.ml1
-rw-r--r--vernac/comDefinition.ml22
-rw-r--r--vernac/comDefinition.mli2
-rw-r--r--vernac/comFixpoint.ml25
-rw-r--r--vernac/comFixpoint.mli4
-rw-r--r--vernac/comHints.ml30
-rw-r--r--vernac/comPrimitive.ml2
-rw-r--r--vernac/comProgramFixpoint.ml32
-rw-r--r--vernac/comProgramFixpoint.mli2
-rw-r--r--vernac/comSearch.ml14
-rw-r--r--vernac/declare.ml101
-rw-r--r--vernac/declare.mli8
-rw-r--r--vernac/declaremods.mli2
-rw-r--r--vernac/egramcoq.ml4
-rw-r--r--vernac/g_proofs.mlg2
-rw-r--r--vernac/g_vernac.mlg4
-rw-r--r--vernac/library.ml4
-rw-r--r--vernac/metasyntax.ml29
-rw-r--r--vernac/prettyp.ml4
-rw-r--r--vernac/proof_using.ml26
-rw-r--r--vernac/proof_using.mli5
-rw-r--r--vernac/record.ml2
-rw-r--r--vernac/search.ml20
-rw-r--r--vernac/vernacentries.ml103
373 files changed, 13664 insertions, 8735 deletions
diff --git a/.gitignore b/.gitignore
index bdd692420f..aab1d1ede7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -155,6 +155,7 @@ kernel/byterun/coq_jumptbl.h
kernel/genOpcodeFiles.exe
kernel/vmopcodes.ml
kernel/uint63.ml
+kernel/float64.ml
ide/coqide/default.bindings
ide/coqide/default_bindings_src.exe
ide/coqide/index_urls.txt
diff --git a/Makefile.common b/Makefile.common
index a482b9b963..caf1821ce5 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -149,11 +149,9 @@ CCCMO:=plugins/cc/cc_plugin.cmo
BTAUTOCMO:=plugins/btauto/btauto_plugin.cmo
RTAUTOCMO:=plugins/rtauto/rtauto_plugin.cmo
SYNTAXCMO:=$(addprefix plugins/syntax/, \
- r_syntax_plugin.cmo \
int63_syntax_plugin.cmo \
float_syntax_plugin.cmo \
- numeral_notation_plugin.cmo \
- string_notation_plugin.cmo)
+ number_string_notation_plugin.cmo)
DERIVECMO:=plugins/derive/derive_plugin.cmo
LTACCMO:=plugins/ltac/ltac_plugin.cmo plugins/ltac/tauto_plugin.cmo
SSRMATCHINGCMO:=plugins/ssrmatching/ssrmatching_plugin.cmo
diff --git a/Makefile.doc b/Makefile.doc
index 473a70fb72..a5ff8e0123 100644
--- a/Makefile.doc
+++ b/Makefile.doc
@@ -248,8 +248,7 @@ $(DOC_GRAM): $(DOC_GRAMCMO) coqpp/coqpp_parser.mli coqpp/coqpp_parser.ml doc/too
# user-contrib/*/*.mlg omitted for now (e.g. ltac2)
PLUGIN_MLGS := $(wildcard plugins/*/*.mlg)
-OMITTED_PLUGIN_MLGS := plugins/ssr/ssrparser.mlg plugins/ssr/ssrvernac.mlg plugins/ssrmatching/g_ssrmatching.mlg \
- plugins/ssrsearch/g_search.mlg
+OMITTED_PLUGIN_MLGS :=
DOC_MLGS := $(wildcard */*.mlg) $(sort $(filter-out $(OMITTED_PLUGIN_MLGS), $(PLUGIN_MLGS))) \
user-contrib/Ltac2/g_ltac2.mlg
DOC_EDIT_MLGS := $(wildcard doc/tools/docgram/*.edit_mlg)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 41b5210f45..46bd4367a7 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -62,16 +62,9 @@ jobs:
- script: |
set -e
- brew update
- (cd $(brew --repository)/Library/Taps/homebrew/homebrew-core/ && git fetch --shallow-since=${HBCORE_DATE} && git checkout ${HBCORE_REF})
- brew install gnu-time opam pkg-config gtksourceview3 adwaita-icon-theme gmp || true
- # || true: workaround #12657, see also #12672 and commit message for this line
+ brew install gnu-time opam gtksourceview3 adwaita-icon-theme
pip3 install macpack
displayName: 'Install system dependencies'
- env:
- HOMEBREW_NO_AUTO_UPDATE: "1"
- HBCORE_DATE: "2019-09-03"
- HBCORE_REF: "44ee64cf4b9f2d2bf000758d356db0c77425e42e"
- script: |
set -e
@@ -107,17 +100,17 @@ jobs:
make install
displayName: 'Install Coq'
- - script: |
- set -e
- eval $(opam env)
- export PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig
- ./dev/build/osx/make-macos-dmg.sh
- mv _build/*.dmg "$(Build.ArtifactStagingDirectory)/"
- displayName: 'Create the dmg bundle'
- env:
- OUTDIR: '$(Build.BinariesDirectory)'
-
- - task: PublishBuildArtifacts@1
- inputs:
- pathtoPublish: '$(Build.ArtifactStagingDirectory)'
- artifactName: coq-macOS-installer
+# - script: |
+# set -e
+# eval $(opam env)
+# export PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig
+# ./dev/build/osx/make-macos-dmg.sh
+# mv _build/*.dmg "$(Build.ArtifactStagingDirectory)/"
+# displayName: 'Create the dmg bundle'
+# env:
+# OUTDIR: '$(Build.BinariesDirectory)'
+
+# - task: PublishBuildArtifacts@1
+# inputs:
+# pathtoPublish: '$(Build.ArtifactStagingDirectory)'
+# artifactName: coq-macOS-installer
diff --git a/checker/values.ml b/checker/values.ml
index 38cb243f80..4e99d087df 100644
--- a/checker/values.ml
+++ b/checker/values.ml
@@ -374,7 +374,7 @@ and v_modtype =
let v_vodigest = Sum ("module_impl",0, [| [|String|]; [|String;String|] |])
let v_deps = Array (v_tuple "dep" [|v_dp;v_vodigest|])
let v_compiled_lib =
- v_tuple "compiled" [|v_dp;v_module;v_context_set;v_deps;v_engagement;Any|]
+ v_tuple "compiled" [|v_dp;v_module;v_context_set;v_deps;v_engagement|]
(** Library objects *)
diff --git a/coqpp/coqpp_main.ml b/coqpp/coqpp_main.ml
index 83929bd030..8affe58824 100644
--- a/coqpp/coqpp_main.ml
+++ b/coqpp/coqpp_main.ml
@@ -454,7 +454,7 @@ struct
let terminal s =
let p =
- if s <> "" && s.[0] >= '0' && s.[0] <= '9' then "CLexer.terminal_numeral"
+ if s <> "" && s.[0] >= '0' && s.[0] <= '9' then "CLexer.terminal_number"
else "CLexer.terminal" in
let c = Printf.sprintf "Pcoq.Symbol.token (%s \"%s\")" p s in
SymbQuote c
diff --git a/dev/ci/ci-iris.sh b/dev/ci/ci-iris.sh
index 9616f3ce00..d29e6f1635 100755
--- a/dev/ci/ci-iris.sh
+++ b/dev/ci/ci-iris.sh
@@ -9,13 +9,15 @@ git_download iris_string_ident
git_download iris_examples
# Extract required version of Iris (avoiding "+" which does not work on MacOS :( *)
-iris_CI_REF=$(grep -F '"coq-iris"' < "${CI_BUILD_DIR}/iris_examples/coq-iris-examples.opam" | sed 's/.*"dev\.[0-9][0-9.-]*\.\([0-9a-z][0-9a-z]*\)".*/\1/')
+iris_CI_REF=$(grep -F '"coq-iris-heap-lang"' < "${CI_BUILD_DIR}/iris_examples/coq-iris-examples.opam" | sed 's/.*"dev\.[0-9][0-9.-]*\.\([0-9a-z][0-9a-z]*\)".*/\1/')
+[ -n "$iris_CI_REF" ] || { echo "Could not find Iris dependency version" && exit 1; }
# Setup Iris
git_download iris
# Extract required version of std++
stdpp_CI_REF=$(grep -F '"coq-stdpp"' < "${CI_BUILD_DIR}/iris/coq-iris.opam" | sed 's/.*"dev\.[0-9][0-9.-]*\.\([0-9a-z][0-9a-z]*\)".*/\1/')
+[ -n "$stdpp_CI_REF" ] || { echo "Could not find stdpp dependency version" && exit 1; }
# Setup std++
git_download stdpp
diff --git a/dev/ci/user-overlays/12218-proux01-numeral-notations-non-inductive.sh b/dev/ci/user-overlays/12218-proux01-numeral-notations-non-inductive.sh
new file mode 100644
index 0000000000..d9b49ad0d1
--- /dev/null
+++ b/dev/ci/user-overlays/12218-proux01-numeral-notations-non-inductive.sh
@@ -0,0 +1,18 @@
+if [ "$CI_PULL_REQUEST" = "12218" ] || [ "$CI_BRANCH" = "numeral-notations-non-inductive" ]; then
+
+ stdlib2_CI_REF=numeral-notations-non-inductive
+ stdlib2_CI_GITURL=https://github.com/proux01/stdlib2
+
+ hott_CI_REF=numeral-notations-non-inductive
+ hott_CI_GITURL=https://github.com/proux01/HoTT
+
+ paramcoq_CI_REF=numeral-notations-non-inductive
+ paramcoq_CI_GITURL=https://github.com/proux01/paramcoq
+
+ quickchick_CI_REF=numeral-notations-non-inductive
+ quickchick_CI_GITURL=https://github.com/proux01/QuickChick
+
+ metacoq_CI_REF=numeral-notations-non-inductive
+ metacoq_CI_GITURL=https://github.com/proux01/metacoq
+
+fi
diff --git a/dev/ci/user-overlays/13139-ppedrot-clean-hint-constr.sh b/dev/ci/user-overlays/13139-ppedrot-clean-hint-constr.sh
new file mode 100644
index 0000000000..2f70f43a2b
--- /dev/null
+++ b/dev/ci/user-overlays/13139-ppedrot-clean-hint-constr.sh
@@ -0,0 +1,9 @@
+if [ "$CI_PULL_REQUEST" = "13139" ] || [ "$CI_BRANCH" = "clean-hint-constr" ]; then
+
+ equations_CI_REF=clean-hint-constr
+ equations_CI_GITURL=https://github.com/ppedrot/Coq-Equations
+
+ fiat_parsers_CI_REF=clean-hint-constr
+ fiat_parsers_CI_GITURL=https://github.com/ppedrot/fiat
+
+fi
diff --git a/dev/doc/changes.md b/dev/doc/changes.md
index 6a6318f97a..5adeafaa38 100644
--- a/dev/doc/changes.md
+++ b/dev/doc/changes.md
@@ -30,6 +30,13 @@ Generic arguments:
- Generic arguments: `wit_var` is deprecated, use `wit_hyp`.
+Dumpglob:
+
+- The function `Dumpglob.pause` and `Dumpglob.continue` are replaced
+ by `Dumpglob.push_output` and `Dumpglob.pop_output`. This allows
+ plugins to temporarily change/pause the output of Dumpglob, and then
+ restore it to the original setting.
+
## Changes between Coq 8.11 and Coq 8.12
### Code formatting
diff --git a/dev/doc/critical-bugs b/dev/doc/critical-bugs
index 066facd5db..37619833ac 100644
--- a/dev/doc/critical-bugs
+++ b/dev/doc/critical-bugs
@@ -312,6 +312,18 @@ Conversion machines
risk: none without using -allow-sprop (off by default in 8.10.0),
otherwise could be exploited by mistake
+Side-effects
+
+ component: side-effects
+ summary: polymorphic side-effects inside monomorphic definitions incorrectly handled as not inlined
+ introduced: ?
+ impacted released versions: at least from 8.6 to 8.12.0
+ impacted coqchk versions: none (no side-effects in the checker)
+ found by: ppedrot
+ exploit: test-suite/bugs/closed/bug_13330.v
+ GH issue number: #13330
+ risk: unlikely to be exploited by mistake, requires the use of unsafe tactics
+
Conflicts with axioms in library
component: library of real numbers
diff --git a/dev/doc/shield-icon.png b/dev/doc/shield-icon.png
index 629e51a819..f4a5b6ff5e 100644
--- a/dev/doc/shield-icon.png
+++ b/dev/doc/shield-icon.png
Binary files differ
diff --git a/doc/changelog/01-kernel/12738-fix-sr-cumul-inds.rst b/doc/changelog/01-kernel/12738-fix-sr-cumul-inds.rst
deleted file mode 100644
index 1bf62de3fd..0000000000
--- a/doc/changelog/01-kernel/12738-fix-sr-cumul-inds.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-- **Fixed:** Incompleteness of conversion checking on problems
- involving :ref:`eta-expansion` and :ref:`cumulative universe
- polymorphic inductive types <cumulative>` (`#12738
- <https://github.com/coq/coq/pull/12738>`_, fixes `#7015
- <https://github.com/coq/coq/issues/7015>`_, by Gaëtan Gilbert).
diff --git a/doc/changelog/01-kernel/13356-primarray-cumul.rst b/doc/changelog/01-kernel/13356-primarray-cumul.rst
new file mode 100644
index 0000000000..978ca325bf
--- /dev/null
+++ b/doc/changelog/01-kernel/13356-primarray-cumul.rst
@@ -0,0 +1,5 @@
+- **Changed:** Primitive arrays are now irrelevant in their single
+ polymorphic universe (same as a polymorphic cumulative list
+ inductive would be) (`#13356
+ <https://github.com/coq/coq/pull/13356>`_, fixes `#13354
+ <https://github.com/coq/coq/issues/13354>`_, by Gaëtan Gilbert).
diff --git a/doc/changelog/02-specification-language/13183-using-att.rst b/doc/changelog/02-specification-language/13183-using-att.rst
new file mode 100644
index 0000000000..c380d932ed
--- /dev/null
+++ b/doc/changelog/02-specification-language/13183-using-att.rst
@@ -0,0 +1,6 @@
+- **Added:**
+ Definition and (Co)Fixpoint now support the :attr:`using` attribute.
+ It has the same effect as :cmd:`Proof using`, which is only available in
+ interactive mode.
+ (`#13183 <https://github.com/coq/coq/pull/13183>`_,
+ by Enrico Tassi).
diff --git a/doc/changelog/02-specification-language/13217-master+fix13216-typeclass-for-match-return-clause.rst b/doc/changelog/02-specification-language/13217-master+fix13216-typeclass-for-match-return-clause.rst
new file mode 100644
index 0000000000..2d8230b965
--- /dev/null
+++ b/doc/changelog/02-specification-language/13217-master+fix13216-typeclass-for-match-return-clause.rst
@@ -0,0 +1,5 @@
+- **Fixed:**
+ Allow use of type classes inference for the return predicate of a :n:`match`
+ (was deactivated in versions 8.10 to 8.12, `#13217 <https://github.com/coq/coq/pull/13217>`_,
+ fixes `#13216 <https://github.com/coq/coq/issues/13216>`_,
+ by Hugo Herbelin).
diff --git a/doc/changelog/03-notations/12099-master+constraining-terms-occurring-also-as-pattern-in-notations.rst b/doc/changelog/03-notations/12099-master+constraining-terms-occurring-also-as-pattern-in-notations.rst
new file mode 100644
index 0000000000..e9b02aed6d
--- /dev/null
+++ b/doc/changelog/03-notations/12099-master+constraining-terms-occurring-also-as-pattern-in-notations.rst
@@ -0,0 +1,4 @@
+- **Changed:**
+ Improved support for notations/abbreviations with mixed terms and patterns (such as the forcing modality)
+ (`#12099 <https://github.com/coq/coq/pull/12099>`_,
+ by Hugo Herbelin).
diff --git a/doc/changelog/03-notations/12218-numeral-notations-non-inductive.rst b/doc/changelog/03-notations/12218-numeral-notations-non-inductive.rst
new file mode 100644
index 0000000000..5ea37e7494
--- /dev/null
+++ b/doc/changelog/03-notations/12218-numeral-notations-non-inductive.rst
@@ -0,0 +1,19 @@
+- **Deprecated**
+ ``Numeral.v`` is deprecated, please use ``Number.v`` instead.
+- **Changed**
+ Rational and real constants are parsed differently.
+ The exponent is now encoded separately from the fractional part
+ using ``Z.pow_pos``. This way, parsing large exponents can no longer
+ blow up and constants are printed in a form closer to the one they
+ were parsed (i.e., ``102e-2`` is reprinted as such and not ``1.02``).
+- **Removed**
+ OCaml parser and printer for real constants have been removed.
+ Real constants are now handled with proven Coq code.
+- **Added:**
+ :ref:`Number Notation <number-notations>` and :ref:`String Notation
+ <string-notations>` commands now
+ support parameterized inductive and non inductive types
+ (`#12218 <https://github.com/coq/coq/pull/12218>`_,
+ fixes `#12035 <https://github.com/coq/coq/issues/12035>`_,
+ by Pierre Roux, review by Jason Gross and Jim Fehrle for the
+ reference manual).
diff --git a/doc/changelog/03-notations/12946-master+fix12908-part1-collision-lonely-notation-printing.rst b/doc/changelog/03-notations/12946-master+fix12908-part1-collision-lonely-notation-printing.rst
deleted file mode 100644
index 95a9093272..0000000000
--- a/doc/changelog/03-notations/12946-master+fix12908-part1-collision-lonely-notation-printing.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-- **Fixed:**
- Undetected collision between a lonely notation and a notation in
- scope at printing time
- (`#12946 <https://github.com/coq/coq/pull/12946>`_,
- fixes the first part of `#12908 <https://github.com/coq/coq/issues/12908>`_,
- by Hugo Herbelin).
diff --git a/doc/changelog/03-notations/13026-master+fix-printing-custom-no-level-8.2.rst b/doc/changelog/03-notations/13026-master+fix-printing-custom-no-level-8.2.rst
deleted file mode 100644
index 42b62eed75..0000000000
--- a/doc/changelog/03-notations/13026-master+fix-printing-custom-no-level-8.2.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-- **Fixed:**
- Fixing printing of notations in custom entries with
- variables not mentioning an explicit level
- (`#13026 <https://github.com/coq/coq/pull/13026>`_,
- fixes `#12775 <https://github.com/coq/coq/issues/12775>`_
- and `#13018 <https://github.com/coq/coq/issues/13018>`_,
- by Hugo Herbelin).
diff --git a/doc/changelog/03-notations/13067-master+fix-display-parentheses-default-coqide.rst b/doc/changelog/03-notations/13067-master+fix-display-parentheses-default-coqide.rst
deleted file mode 100644
index 50aa4a9052..0000000000
--- a/doc/changelog/03-notations/13067-master+fix-display-parentheses-default-coqide.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-- **Fixed:**
- Repairing option :g:`Display parentheses` in CoqIDE
- (`#12794 <https://github.com/coq/coq/pull/12794>`_ and `#13067 <https://github.com/coq/coq/pull/13067>`_,
- fixes `#12793 <https://github.com/coq/coq/issues/12793>`_,
- by Jean-Christophe Léchenet and Hugo Herbelin).
diff --git a/doc/changelog/03-notations/13092-master+fix-13078-no-binder-in-pattern-notation.rst b/doc/changelog/03-notations/13092-master+fix-13078-no-binder-in-pattern-notation.rst
new file mode 100644
index 0000000000..fb12c91729
--- /dev/null
+++ b/doc/changelog/03-notations/13092-master+fix-13078-no-binder-in-pattern-notation.rst
@@ -0,0 +1,5 @@
+- **Fixed:**
+ Preventing notations for constructors to involve binders
+ (`#13092 <https://github.com/coq/coq/pull/13092>`_,
+ fixes `#13078 <https://github.com/coq/coq/issues/13078>`_,
+ by Hugo Herbelin).
diff --git a/doc/changelog/04-tactics/12816-master+fix12787-K-redex-injection-anomaly.rst b/doc/changelog/04-tactics/12816-master+fix12787-K-redex-injection-anomaly.rst
deleted file mode 100644
index 289d17167d..0000000000
--- a/doc/changelog/04-tactics/12816-master+fix12787-K-redex-injection-anomaly.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-- **Fixed:**
- Anomaly with :tacn:`injection` involving artificial
- dependencies disappearing by reduction
- (`#12816 <https://github.com/coq/coq/pull/12816>`_,
- fixes `#12787 <https://github.com/coq/coq/issues/12787>`_,
- by Hugo Herbelin).
diff --git a/doc/changelog/04-tactics/12847-master+inversion-works-with-eq-in-type.rst b/doc/changelog/04-tactics/12847-master+inversion-works-with-eq-in-type.rst
deleted file mode 100644
index b444a2f436..0000000000
--- a/doc/changelog/04-tactics/12847-master+inversion-works-with-eq-in-type.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-- **Added:**
- :tacn:`replace` and :tacn:`inversion` support registration of a
- :g:`core.identity`-like equality in :g:`Type`, such as HoTT's :g:`path`
- (`#12847 <https://github.com/coq/coq/pull/12847>`_,
- partially fixes `#12846 <https://github.com/coq/coq/issues/12846>`_,
- by Hugo Herbelin).
diff --git a/doc/changelog/05-tactic-language/13232-ltac2-if-then-else.rst b/doc/changelog/05-tactic-language/13232-ltac2-if-then-else.rst
new file mode 100644
index 0000000000..d105561a23
--- /dev/null
+++ b/doc/changelog/05-tactic-language/13232-ltac2-if-then-else.rst
@@ -0,0 +1,5 @@
+- **Added:**
+ An if-then-else syntax to Ltac2
+ (`#13232 <https://github.com/coq/coq/pull/13232>`_,
+ fixes `#10110 <https://github.com/coq/coq/issues/10110>`_,
+ by Pierre-Marie Pédrot).
diff --git a/doc/changelog/06-ssreflect/12857-changelog-for-12857.rst b/doc/changelog/06-ssreflect/12857-changelog-for-12857.rst
deleted file mode 100644
index 4350fd0238..0000000000
--- a/doc/changelog/06-ssreflect/12857-changelog-for-12857.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-- **Fixed:**
- Regression in error reporting after :tacn:`case <case (ssreflect)>`.
- A generic error message "Could not fill dependent hole in apply" was
- reported for any error following :tacn:`case <case (ssreflect)>` or
- :tacn:`elim <elim (ssreflect)>`
- (`#12857 <https://github.com/coq/coq/pull/12857>`_,
- fixes `#12837 <https://github.com/coq/coq/issues/12837>`_,
- by Enrico Tassi).
diff --git a/doc/changelog/06-ssreflect/13317-ssr_dup_swap_apply_ipat.rst b/doc/changelog/06-ssreflect/13317-ssr_dup_swap_apply_ipat.rst
new file mode 100644
index 0000000000..8d1564533d
--- /dev/null
+++ b/doc/changelog/06-ssreflect/13317-ssr_dup_swap_apply_ipat.rst
@@ -0,0 +1,4 @@
+- **Added:**
+ SSReflect intro pattern ltac views ``/[dup]``, ``/[swap]`` and ``/[apply]``
+ (`#13317 <https://github.com/coq/coq/pull/13317>`_,
+ by Cyril Cohen).
diff --git a/doc/changelog/07-commands-and-options/13139-clean-hint-constr.rst b/doc/changelog/07-commands-and-options/13139-clean-hint-constr.rst
new file mode 100644
index 0000000000..1a6bc88c6c
--- /dev/null
+++ b/doc/changelog/07-commands-and-options/13139-clean-hint-constr.rst
@@ -0,0 +1,6 @@
+- **Changed:**
+ When declaring arbitrary terms as hints, unsolved
+ evars are not abstracted implicitly anymore and instead
+ raise an error
+ (`#13139 <https://github.com/coq/coq/pull/13139>`_,
+ by Pierre-Marie Pédrot).
diff --git a/doc/changelog/07-commands-and-options/13255-master+fix13244-use-coercions-in-search.rst b/doc/changelog/07-commands-and-options/13255-master+fix13244-use-coercions-in-search.rst
new file mode 100644
index 0000000000..03be92f897
--- /dev/null
+++ b/doc/changelog/07-commands-and-options/13255-master+fix13244-use-coercions-in-search.rst
@@ -0,0 +1,7 @@
+- **Added:**
+ Added support for automatic insertion of coercions in :cmd:`Search`
+ patterns. Additionally, head patterns are now automatically
+ interpreted as types
+ (`#13255 <https://github.com/coq/coq/pull/13255>`_,
+ fixes `#13244 <https://github.com/coq/coq/issues/13244>`_,
+ by Hugo Herbelin).
diff --git a/doc/changelog/07-commands-and-options/13339-proof-using-noinit.rst b/doc/changelog/07-commands-and-options/13339-proof-using-noinit.rst
new file mode 100644
index 0000000000..9ae759be56
--- /dev/null
+++ b/doc/changelog/07-commands-and-options/13339-proof-using-noinit.rst
@@ -0,0 +1,5 @@
+- **Added:**
+ The :cmd:`Proof using` command can now be used without loading the
+ Ltac plugin (`-noinit` mode)
+ (`#13339 <https://github.com/coq/coq/pull/13339>`_,
+ by Théo Zimmermann).
diff --git a/doc/changelog/07-commands-and-options/13345-master+doc-add-ml-path-not-exported.rst b/doc/changelog/07-commands-and-options/13345-master+doc-add-ml-path-not-exported.rst
new file mode 100644
index 0000000000..dc8010b456
--- /dev/null
+++ b/doc/changelog/07-commands-and-options/13345-master+doc-add-ml-path-not-exported.rst
@@ -0,0 +1,5 @@
+- **Added:**
+ Clarify in the documentation that :cmd:`Add ML Path` is not exported to compiled files
+ (`#13345 <https://github.com/coq/coq/pull/13345>`_,
+ fixes `#13344 <https://github.com/coq/coq/issues/13344>`_,
+ by Hugo Herbelin).
diff --git a/doc/changelog/08-tools/12754-master+fix-coqdoc-index-escaping.rst b/doc/changelog/08-tools/12754-master+fix-coqdoc-index-escaping.rst
deleted file mode 100644
index a05829b720..0000000000
--- a/doc/changelog/08-tools/12754-master+fix-coqdoc-index-escaping.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-- **Fixed:**
- Special symbols now escaped in the index produced by coqdoc,
- avoiding collision with the syntax of the output format
- (`#12754 <https://github.com/coq/coq/pull/12754>`_,
- fixes `#12752 <https://github.com/coq/coq/issues/12752>`_,
- by Hugo Herbelin).
diff --git a/doc/changelog/08-tools/12772-fix-details.rst b/doc/changelog/08-tools/12772-fix-details.rst
deleted file mode 100644
index 67ee061285..0000000000
--- a/doc/changelog/08-tools/12772-fix-details.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-- **Fixed:**
- The `details` environment added in the 8.12 release can now be used
- as advertised in the reference manual
- (`#12772 <https://github.com/coq/coq/pull/12772>`_,
- by Thomas Letan).
diff --git a/doc/changelog/08-tools/13063-fix-no-output-sync-make-file.rst b/doc/changelog/08-tools/13063-fix-no-output-sync-make-file.rst
deleted file mode 100644
index 75b1e26248..0000000000
--- a/doc/changelog/08-tools/13063-fix-no-output-sync-make-file.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-- **Fixed:**
- Targets such as ``print-pretty-timed`` in ``coq_makefile``-made
- ``Makefile``\s no longer error in rare cases where ``--output-sync`` is not
- passed to make and the timing output gets interleaved in just the wrong way
- (`#13063 <https://github.com/coq/coq/pull/13063>`_, fixes `#13062
- <https://github.com/coq/coq/issues/13062>`_, by Jason Gross).
diff --git a/doc/changelog/09-coqide/00000-title.rst b/doc/changelog/09-coqide/00000-title.rst
index c95e2133d6..0fc27cf380 100644
--- a/doc/changelog/09-coqide/00000-title.rst
+++ b/doc/changelog/09-coqide/00000-title.rst
@@ -1,3 +1,3 @@
-**|CoqIDE|**
+**CoqIDE**
diff --git a/doc/changelog/09-coqide/13145-master+coqide-printing-goal-names-support.rst b/doc/changelog/09-coqide/13145-master+coqide-printing-goal-names-support.rst
new file mode 100644
index 0000000000..f7446cc5aa
--- /dev/null
+++ b/doc/changelog/09-coqide/13145-master+coqide-printing-goal-names-support.rst
@@ -0,0 +1,4 @@
+- **Added:**
+ Support for flag :flag:`Printing Goal Names` in View menu
+ (`#13145 <https://github.com/coq/coq/pull/13145>`_,
+ by Hugo Herbelin).
diff --git a/doc/changelog/10-standard-library/12420-decidable.rst b/doc/changelog/10-standard-library/12420-decidable.rst
new file mode 100644
index 0000000000..6a4da91fa3
--- /dev/null
+++ b/doc/changelog/10-standard-library/12420-decidable.rst
@@ -0,0 +1,4 @@
+- **Added:**
+ ``Decidable`` instance for negation
+ (`#12420 <https://github.com/coq/coq/pull/12420>`_,
+ by Yishuai Li).
diff --git a/doc/changelog/11-infrastructure-and-dependencies/12864-fix-approve-output.rst b/doc/changelog/11-infrastructure-and-dependencies/12864-fix-approve-output.rst
deleted file mode 100644
index c754826e62..0000000000
--- a/doc/changelog/11-infrastructure-and-dependencies/12864-fix-approve-output.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-- **Fixed:**
- ``make approve-output`` in the test-suite now correctly handles
- ``output-coqtop`` and ``output-coqchk`` tests (`#12864
- <https://github.com/coq/coq/pull/12864>`_, fixes `#12863
- <https://github.com/coq/coq/issues/12863>`_, by Jason Gross).
diff --git a/doc/changelog/11-infrastructure-and-dependencies/12972-ocaml+4_11.rst b/doc/changelog/11-infrastructure-and-dependencies/12972-ocaml+4_11.rst
deleted file mode 100644
index 855aa360f1..0000000000
--- a/doc/changelog/11-infrastructure-and-dependencies/12972-ocaml+4_11.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-- **Added:**
- Coq is now tested against OCaml 4.11.1
- (`#12972 <https://github.com/coq/coq/pull/12972>`_,
- by Emilio Jesus Gallego Arias).
diff --git a/doc/changelog/11-infrastructure-and-dependencies/13011-sphinx-3.rst b/doc/changelog/11-infrastructure-and-dependencies/13011-sphinx-3.rst
deleted file mode 100644
index d17a2dff6b..0000000000
--- a/doc/changelog/11-infrastructure-and-dependencies/13011-sphinx-3.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-- **Fixed:**
- The reference manual can now build with Sphinx 3
- (`#13011 <https://github.com/coq/coq/pull/13011>`_,
- fixes `#12332 <https://github.com/coq/coq/issues/12332>`_,
- by Théo Zimmermann and Jim Fehrle).
diff --git a/doc/sphinx/README.rst b/doc/sphinx/README.rst
index 4461ff9240..bfdbc4c4db 100644
--- a/doc/sphinx/README.rst
+++ b/doc/sphinx/README.rst
@@ -551,7 +551,7 @@ Add either ``abort`` to the first block or ``reset`` to the second block to avoi
Abbreviations and macros
------------------------
-Substitutions for specially-formatted names (like ``|Cic|``, ``|Coq|``, ``|CoqIDE|``, ``|Ltac|``, and ``|Gallina|``), along with some useful LaTeX macros, are defined in a `separate file </doc/sphinx/refman-preamble.rst>`_. This file is automatically included in all manual pages.
+Substitutions for specially-formatted names (like ``|Cic|``, ``|Ltac|`` and ``|Latex|``), along with some useful LaTeX macros, are defined in a `separate file </doc/sphinx/refman-preamble.rst>`_. This file is automatically included in all manual pages.
Emacs
-----
diff --git a/doc/sphinx/README.template.rst b/doc/sphinx/README.template.rst
index b4e21aa14a..d4e297299e 100644
--- a/doc/sphinx/README.template.rst
+++ b/doc/sphinx/README.template.rst
@@ -290,7 +290,7 @@ Add either ``abort`` to the first block or ``reset`` to the second block to avoi
Abbreviations and macros
------------------------
-Substitutions for specially-formatted names (like ``|Cic|``, ``|Coq|``, ``|CoqIDE|``, ``|Ltac|``, and ``|Gallina|``), along with some useful LaTeX macros, are defined in a `separate file </doc/sphinx/refman-preamble.rst>`_. This file is automatically included in all manual pages.
+Substitutions for specially-formatted names (like ``|Cic|``, ``|Ltac|`` and ``|Latex|``), along with some useful LaTeX macros, are defined in a `separate file </doc/sphinx/refman-preamble.rst>`_. This file is automatically included in all manual pages.
Emacs
-----
diff --git a/doc/sphinx/addendum/extraction.rst b/doc/sphinx/addendum/extraction.rst
index 96e115fc3d..3662822a5e 100644
--- a/doc/sphinx/addendum/extraction.rst
+++ b/doc/sphinx/addendum/extraction.rst
@@ -5,10 +5,10 @@ Program extraction
:Authors: Jean-Christophe Filliâtre and Pierre Letouzey
-We present here the |Coq| extraction commands, used to build certified
+We present here the Coq extraction commands, used to build certified
and relatively efficient functional programs, extracting them from
-either |Coq| functions or |Coq| proofs of specifications. The
-functional languages available as output are currently |OCaml|, Haskell
+either Coq functions or Coq proofs of specifications. The
+functional languages available as output are currently OCaml, Haskell
and Scheme. In the following, "ML" will be used (abusively) to refer
to any of the three.
@@ -16,7 +16,7 @@ Before using any of the commands or options described in this chapter,
the extraction framework should first be loaded explicitly
via ``Require Extraction``, or via the more robust
``From Coq Require Extraction``.
-Note that in earlier versions of |Coq|, these commands and options were
+Note that in earlier versions of Coq, these commands and options were
directly available without any preliminary ``Require``.
.. coqtop:: in
@@ -29,23 +29,23 @@ Generating ML Code
.. note::
In the following, a qualified identifier :token:`qualid`
- can be used to refer to any kind of |Coq| global "object" : constant,
+ can be used to refer to any kind of Coq global "object" : constant,
inductive type, inductive constructor or module name.
The next two commands are meant to be used for rapid preview of
-extraction. They both display extracted term(s) inside |Coq|.
+extraction. They both display extracted term(s) inside Coq.
.. cmd:: Extraction @qualid
- Extraction of the mentioned object in the |Coq| toplevel.
+ Extraction of the mentioned object in the Coq toplevel.
.. cmd:: Recursive Extraction {+ @qualid }
Recursive extraction of all the mentioned objects and
- all their dependencies in the |Coq| toplevel.
+ all their dependencies in the Coq toplevel.
All the following commands produce real ML files. User can choose to
-produce one monolithic file or one file per |Coq| library.
+produce one monolithic file or one file per Coq library.
.. cmd:: Extraction @string {+ @qualid }
@@ -57,14 +57,14 @@ produce one monolithic file or one file per |Coq| library.
.. cmd:: Extraction Library @ident
- Extraction of the whole |Coq| library :n:`@ident.v` to an ML module
+ Extraction of the whole Coq library :n:`@ident.v` to an ML module
:n:`@ident.ml`. In case of name clash, identifiers are here renamed
using prefixes ``coq_`` or ``Coq_`` to ensure a session-independent
renaming.
.. cmd:: Recursive Extraction Library @ident
- Extraction of the |Coq| library :n:`@ident.v` and all other modules
+ Extraction of the Coq library :n:`@ident.v` and all other modules
:n:`@ident.v` depends on.
.. cmd:: Separate Extraction {+ @qualid }
@@ -72,26 +72,26 @@ produce one monolithic file or one file per |Coq| library.
Recursive extraction of all the mentioned objects and all
their dependencies, just as :n:`Extraction @string {+ @qualid }`,
but instead of producing one monolithic file, this command splits
- the produced code in separate ML files, one per corresponding |Coq|
+ the produced code in separate ML files, one per corresponding Coq
``.v`` file. This command is hence quite similar to
:cmd:`Recursive Extraction Library`, except that only the needed
- parts of |Coq| libraries are extracted instead of the whole.
+ parts of Coq libraries are extracted instead of the whole.
The naming convention in case of name clash is the same one as
:cmd:`Extraction Library`: identifiers are here renamed using prefixes
``coq_`` or ``Coq_``.
The following command is meant to help automatic testing of
the extraction, see for instance the ``test-suite`` directory
-in the |Coq| sources.
+in the Coq sources.
.. cmd:: Extraction TestCompile {+ @qualid }
All the mentioned objects and all their dependencies are extracted
- to a temporary |OCaml| file, just as in ``Extraction "file"``. Then
+ to a temporary OCaml file, just as in ``Extraction "file"``. Then
this temporary file and its signature are compiled with the same
- |OCaml| compiler used to built |Coq|. This command succeeds only
- if the extraction and the |OCaml| compilation succeed. It fails
- if the current target language of the extraction is not |OCaml|.
+ OCaml compiler used to built Coq. This command succeeds only
+ if the extraction and the OCaml compilation succeed. It fails
+ if the current target language of the extraction is not OCaml.
Extraction Options
-------------------
@@ -120,17 +120,17 @@ Setting the target language
Inlining and optimizations
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Since |OCaml| is a strict language, the extracted code has to
+Since OCaml is a strict language, the extracted code has to
be optimized in order to be efficient (for instance, when using
induction principles we do not want to compute all the recursive calls
but only the needed ones). So the extraction mechanism provides an
automatic optimization routine that will be called each time the user
-wants to generate an |OCaml| program. The optimizations can be split in two
+wants to generate an OCaml program. The optimizations can be split in two
groups: the type-preserving ones (essentially constant inlining and
reductions) and the non type-preserving ones (some function
abstractions of dummy types are removed when it is deemed safe in order
to have more elegant types). Therefore some constants may not appear in the
-resulting monolithic |OCaml| program. In the case of modular extraction,
+resulting monolithic OCaml program. In the case of modular extraction,
even if some inlining is done, the inlined constants are nevertheless
printed, to ensure session-independent programs.
@@ -138,7 +138,7 @@ Concerning Haskell, type-preserving optimizations are less useful
because of laziness. We still make some optimizations, for example in
order to produce more readable code.
-The type-preserving optimizations are controlled by the following |Coq| flags
+The type-preserving optimizations are controlled by the following Coq flags
and commands:
.. flag:: Extraction Optimize
@@ -146,7 +146,7 @@ and commands:
Default is on. This controls all type-preserving optimizations made on
the ML terms (mostly reduction of dummy beta/iota redexes, but also
simplifications on Cases, etc). Turn this flag off if you want a
- ML term as close as possible to the |Coq| term.
+ ML term as close as possible to the Coq term.
.. flag:: Extraction Conservative Types
@@ -199,7 +199,7 @@ The user can explicitly ask for a constant to be extracted by two means:
* by mentioning it on the extraction command line
- * by extracting the whole |Coq| module of this constant.
+ * by extracting the whole Coq module of this constant.
In both cases, the declaration of this constant will be present in the
produced file. But this same constant may or may not be inlined in
@@ -321,7 +321,7 @@ Realizing inductive types
The system also provides a mechanism to specify ML terms for inductive
types and constructors. For instance, the user may want to use the ML
-native boolean type instead of the |Coq| one. The syntax is the following:
+native boolean type instead of the Coq one. The syntax is the following:
.. cmd:: Extract Inductive @qualid => {| @ident | @string } [ {* {| @ident | @string } } ] {? @string__match }
@@ -350,7 +350,7 @@ native boolean type instead of the |Coq| one. The syntax is the following:
arguments is considered to have one unit argument, in order to block
early evaluation of the branch: ``| O => bar`` leads to the functional
form ``(fun () -> bar)``. For instance, when extracting :g:`nat`
- into |OCaml| ``int``, the code to be provided has type:
+ into OCaml ``int``, the code to be provided has type:
``(unit->'a)->(int->'a)->int->'a``.
.. caution:: As for :cmd:`Extract Constant`, this command should be used with care:
@@ -361,15 +361,15 @@ native boolean type instead of the |Coq| one. The syntax is the following:
* Extracting an inductive type to a pre-existing ML inductive type
is quite sound. But extracting to a general type (by providing an
ad-hoc pattern matching) will often **not** be fully rigorously
- correct. For instance, when extracting ``nat`` to |OCaml| ``int``,
+ correct. For instance, when extracting ``nat`` to OCaml ``int``,
it is theoretically possible to build ``nat`` values that are
- larger than |OCaml| ``max_int``. It is the user's responsibility to
+ larger than OCaml ``max_int``. It is the user's responsibility to
be sure that no overflow or other bad events occur in practice.
* Translating an inductive type to an arbitrary ML type does **not**
magically improve the asymptotic complexity of functions, even if the
ML type is an efficient representation. For instance, when extracting
- ``nat`` to |OCaml| ``int``, the function ``Nat.mul`` stays quadratic.
+ ``nat`` to OCaml ``int``, the function ``Nat.mul`` stays quadratic.
It might be interesting to associate this translation with
some specific :cmd:`Extract Constant` when primitive counterparts exist.
@@ -383,9 +383,9 @@ Typical examples are the following:
.. note::
- When extracting to |OCaml|, if an inductive constructor or type has arity 2 and
+ When extracting to OCaml, if an inductive constructor or type has arity 2 and
the corresponding string is enclosed by parentheses, and the string meets
- |OCaml|'s lexical criteria for an infix symbol, then the rest of the string is
+ OCaml's lexical criteria for an infix symbol, then the rest of the string is
used as an infix constructor or type.
.. coqtop:: in
@@ -394,7 +394,7 @@ Typical examples are the following:
Extract Inductive prod => "(*)" [ "(,)" ].
As an example of translation to a non-inductive datatype, let's turn
-``nat`` into |OCaml| ``int`` (see caveat above):
+``nat`` into OCaml ``int`` (see caveat above):
.. coqtop:: in
@@ -404,11 +404,11 @@ Avoiding conflicts with existing filenames
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When using :cmd:`Extraction Library`, the names of the extracted files
-directly depend on the names of the |Coq| files. It may happen that
+directly depend on the names of the Coq files. It may happen that
these filenames are in conflict with already existing files,
either in the standard library of the target language or in other
code that is meant to be linked with the extracted code.
-For instance the module ``List`` exists both in |Coq| and in |OCaml|.
+For instance the module ``List`` exists both in Coq and in OCaml.
It is possible to instruct the extraction not to use particular filenames.
.. cmd:: Extraction Blacklist {+ @ident }
@@ -424,7 +424,7 @@ It is possible to instruct the extraction not to use particular filenames.
Allow the extraction to use any filename.
-For |OCaml|, a typical use of these commands is
+For OCaml, a typical use of these commands is
``Extraction Blacklist String List``.
Additional settings
@@ -440,7 +440,7 @@ Additional settings
Controls which optimizations are used during extraction, providing a finer-grained
control than :flag:`Extraction Optimize`. The bits of :token:`natural` are used as a bit mask.
- Keeping an option off keeps the extracted ML more similar to the |Coq| term.
+ Keeping an option off keeps the extracted ML more similar to the Coq term.
Values are:
+-----+-------+----------------------------------------------------------------+
@@ -471,14 +471,14 @@ Additional settings
.. flag:: Extraction TypeExpand
- If set, fully expand |Coq| types in ML. See the |Coq| source code to learn more.
+ If set, fully expand Coq types in ML. See the Coq source code to learn more.
-Differences between |Coq| and ML type systems
+Differences between Coq and ML type systems
----------------------------------------------
-Due to differences between |Coq| and ML type systems,
+Due to differences between Coq and ML type systems,
some extracted programs are not directly typable in ML.
-We now solve this problem (at least in |OCaml|) by adding
+We now solve this problem (at least in OCaml) by adding
when needed some unsafe casting ``Obj.magic``, which give
a generic type ``'a`` to any term.
@@ -492,7 +492,7 @@ function:
Definition dp {A B:Type}(x:A)(y:B)(f:forall C:Type, C->C) := (f A x, f B y).
-In |OCaml|, for instance, the direct extracted term would be::
+In OCaml, for instance, the direct extracted term would be::
let dp x y f = Pair((f () x),(f () y))
@@ -506,7 +506,7 @@ We now produce the following correct version::
let dp x y f = Pair ((Obj.magic f () x), (Obj.magic f () y))
-Secondly, some |Coq| definitions may have no counterpart in ML. This
+Secondly, some Coq definitions may have no counterpart in ML. This
happens when there is a quantification over types inside the type
of a constructor; for example:
@@ -515,29 +515,29 @@ of a constructor; for example:
Inductive anything : Type := dummy : forall A:Set, A -> anything.
which corresponds to the definition of an ML dynamic type.
-In |OCaml|, we must cast any argument of the constructor dummy
+In OCaml, we must cast any argument of the constructor dummy
(no GADT are produced yet by the extraction).
Even with those unsafe castings, you should never get error like
``segmentation fault``. In fact even if your program may seem
-ill-typed to the |OCaml| type checker, it can't go wrong : it comes
-from a |Coq| well-typed terms, so for example inductive types will always
+ill-typed to the OCaml type checker, it can't go wrong : it comes
+from a Coq well-typed terms, so for example inductive types will always
have the correct number of arguments, etc. Of course, when launching
manually some extracted function, you should apply it to arguments
-of the right shape (from the |Coq| point-of-view).
+of the right shape (from the Coq point-of-view).
More details about the correctness of the extracted programs can be
found in :cite:`Let02`.
We have to say, though, that in most "realistic" programs, these problems do not
-occur. For example all the programs of |Coq| library are accepted by the |OCaml|
+occur. For example all the programs of Coq library are accepted by the OCaml
type checker without any ``Obj.magic`` (see examples below).
Some examples
-------------
We present here two examples of extraction, taken from the
-|Coq| Standard Library. We choose |OCaml| as the target language,
+Coq Standard Library. We choose OCaml as the target language,
but everything, with slight modifications, can also be done in the
other languages supported by extraction.
We then indicate where to find other examples and tests of extraction.
@@ -554,7 +554,7 @@ This module contains a theorem ``eucl_dev``, whose type is::
where ``diveucl`` is a type for the pair of the quotient and the
modulo, plus some logical assertions that disappear during extraction.
-We can now extract this program to |OCaml|:
+We can now extract this program to OCaml:
.. coqtop:: none
@@ -570,11 +570,11 @@ We can now extract this program to |OCaml|:
The inlining of ``gt_wf_rec`` and others is not
mandatory. It only enhances readability of extracted code.
You can then copy-paste the output to a file ``euclid.ml`` or let
-|Coq| do it for you with the following command::
+Coq do it for you with the following command::
Extraction "euclid" eucl_dev.
-Let us play the resulting program (in an |OCaml| toplevel)::
+Let us play the resulting program (in an OCaml toplevel)::
#use "euclid.ml";;
type nat = O | S of nat
@@ -588,7 +588,7 @@ Let us play the resulting program (in an |OCaml| toplevel)::
# eucl_dev (S (S O)) (S (S (S (S (S O)))));;
- : diveucl = Divex (S (S O), S O)
-It is easier to test on |OCaml| integers::
+It is easier to test on OCaml integers::
# let rec nat_of_int = function 0 -> O | n -> S (nat_of_int (n-1));;
val nat_of_int : int -> nat = <fun>
@@ -614,12 +614,12 @@ Extraction's horror museum
~~~~~~~~~~~~~~~~~~~~~~~~~~
Some pathological examples of extraction are grouped in the file
-``test-suite/success/extraction.v`` of the sources of |Coq|.
+``test-suite/success/extraction.v`` of the sources of Coq.
Users' Contributions
~~~~~~~~~~~~~~~~~~~~
-Several of the |Coq| Users' Contributions use extraction to produce
+Several of the Coq Users' Contributions use extraction to produce
certified programs. In particular the following ones have an automatic
extraction test:
diff --git a/doc/sphinx/addendum/generalized-rewriting.rst b/doc/sphinx/addendum/generalized-rewriting.rst
index 407a38378f..27ae7cea3a 100644
--- a/doc/sphinx/addendum/generalized-rewriting.rst
+++ b/doc/sphinx/addendum/generalized-rewriting.rst
@@ -35,7 +35,7 @@ the previous implementation in several ways:
the new implementation, if one provides the proper morphisms. Again,
most of the work is handled in the tactics.
+ First-class morphisms and signatures. Signatures and morphisms are
- ordinary |Coq| terms, hence they can be manipulated inside |Coq|, put
+ ordinary Coq terms, hence they can be manipulated inside Coq, put
inside structures and lemmas about them can be proved inside the
system. Higher-order morphisms are also allowed.
+ Performance. The implementation is based on a depth-first search for
@@ -103,7 +103,7 @@ argument.
Morphisms can also be contravariant in one or more of their arguments.
A morphism is contravariant on an argument associated to the relation
instance :math:`R` if it is covariant on the same argument when the inverse
-relation :math:`R^{−1}` (``inverse R`` in |Coq|) is considered. The special arrow ``-->``
+relation :math:`R^{−1}` (``inverse R`` in Coq) is considered. The special arrow ``-->``
is used in signatures for contravariant morphisms.
Functions having arguments related by symmetric relations instances
@@ -144,7 +144,7 @@ always the intended equality for a given structure.
In the next section we will describe the commands to register terms as
parametric relations and morphisms. Several tactics that deal with
-equality in |Coq| can also work with the registered relations. The exact
+equality in Coq can also work with the registered relations. The exact
list of tactics will be given :ref:`in this section <tactics-enabled-on-user-provided-relations>`.
For instance, the tactic reflexivity can be used to solve a goal ``R n n`` whenever ``R``
is an instance of a registered reflexive relation. However, the
diff --git a/doc/sphinx/addendum/implicit-coercions.rst b/doc/sphinx/addendum/implicit-coercions.rst
index b81212ad0d..0f0ccd6a20 100644
--- a/doc/sphinx/addendum/implicit-coercions.rst
+++ b/doc/sphinx/addendum/implicit-coercions.rst
@@ -8,7 +8,7 @@ Implicit Coercions
General Presentation
---------------------
-This section describes the inheritance mechanism of |Coq|. In |Coq| with
+This section describes the inheritance mechanism of Coq. In Coq with
inheritance, we are not interested in adding any expressive power to
our theory, but only convenience. Given a term, possibly not typable,
we are interested in the problem of determining if it can be well
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index 0942a82d6f..fb9965e43a 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -1,6 +1,6 @@
.. _micromega:
-Micromega: tactics for solving arithmetic goals over ordered rings
+Micromega: solvers for arithmetic goals over ordered rings
==================================================================
:Authors: Frédéric Besson and Evgeny Makarov
@@ -260,7 +260,7 @@ proof by abstracting monomials by variables.
that might miss a refutation.
To illustrate the working of the tactic, consider we wish to prove the
- following |Coq| goal:
+ following Coq goal:
.. needs csdp
.. coqdoc::
diff --git a/doc/sphinx/addendum/miscellaneous-extensions.rst b/doc/sphinx/addendum/miscellaneous-extensions.rst
index 3944a34cdc..7d30cae525 100644
--- a/doc/sphinx/addendum/miscellaneous-extensions.rst
+++ b/doc/sphinx/addendum/miscellaneous-extensions.rst
@@ -1,7 +1,7 @@
Program derivation
==================
-|Coq| comes with an extension called ``Derive``, which supports program
+Coq comes with an extension called ``Derive``, which supports program
derivation. Typically in the style of Bird and Meertens or derivations
of program refinements. To use the Derive extension it must first be
required with ``Require Coq.derive.Derive``. When the extension is loaded,
diff --git a/doc/sphinx/addendum/nsatz.rst b/doc/sphinx/addendum/nsatz.rst
index 85e0cb9536..7a2be3dcef 100644
--- a/doc/sphinx/addendum/nsatz.rst
+++ b/doc/sphinx/addendum/nsatz.rst
@@ -1,6 +1,6 @@
.. _nsatz_chapter:
-Nsatz: tactics for proving equalities in integral domains
+Nsatz: a solver for equalities in integral domains
===========================================================
:Author: Loïc Pottier
diff --git a/doc/sphinx/addendum/omega.rst b/doc/sphinx/addendum/omega.rst
index 35f087d47d..2b10f5671d 100644
--- a/doc/sphinx/addendum/omega.rst
+++ b/doc/sphinx/addendum/omega.rst
@@ -1,6 +1,6 @@
.. _omega_chapter:
-Omega: a solver for quantifier-free problems in Presburger Arithmetic
+Omega: a (deprecated) solver for arithmetic
=====================================================================
:Author: Pierre Crégut
@@ -9,7 +9,7 @@ Omega: a solver for quantifier-free problems in Presburger Arithmetic
The :tacn:`omega` tactic is deprecated in favor of the :tacn:`lia`
tactic. The goal is to consolidate the arithmetic solving
- capabilities of |Coq| into a single engine; moreover, :tacn:`lia` is
+ capabilities of Coq into a single engine; moreover, :tacn:`lia` is
in general more powerful than :tacn:`omega` (it is a complete
Presburger arithmetic solver while :tacn:`omega` was known to be
incomplete).
@@ -143,7 +143,7 @@ Options
.. deprecated:: 8.5
- This deprecated flag (on by default) is for compatibility with |Coq| pre 8.5. It
+ This deprecated flag (on by default) is for compatibility with Coq pre 8.5. It
resets internal name counters to make executions of :tacn:`omega` independent.
.. flag:: Omega UseLocalDefs
diff --git a/doc/sphinx/addendum/parallel-proof-processing.rst b/doc/sphinx/addendum/parallel-proof-processing.rst
index 7a50748c51..e824ae152d 100644
--- a/doc/sphinx/addendum/parallel-proof-processing.rst
+++ b/doc/sphinx/addendum/parallel-proof-processing.rst
@@ -6,8 +6,8 @@ Asynchronous and Parallel Proof Processing
:Author: Enrico Tassi
This chapter explains how proofs can be asynchronously processed by
-|Coq|. This feature improves the reactivity of the system when used in
-interactive mode via |CoqIDE|. In addition, it allows |Coq| to take
+Coq. This feature improves the reactivity of the system when used in
+interactive mode via CoqIDE. In addition, it allows Coq to take
advantage of parallel hardware when used as a batch compiler by
decoupling the checking of statements and definitions from the
construction and checking of proofs objects.
@@ -20,13 +20,13 @@ This feature has some technical limitations that may make it
unsuitable for some use cases.
For example, in interactive mode, some errors coming from the kernel
-of |Coq| are signaled late. The type of errors belonging to this
+of Coq are signaled late. The type of errors belonging to this
category are universe inconsistencies.
At the time of writing, only opaque proofs (ending with ``Qed`` or
``Admitted``) can be processed asynchronously.
-Finally, asynchronous processing is disabled when running |CoqIDE| in
+Finally, asynchronous processing is disabled when running CoqIDE in
Windows. The current implementation of the feature is not stable on
Windows. It can be enabled, as described below at :ref:`interactive-mode`,
though doing so is not recommended.
@@ -34,12 +34,12 @@ though doing so is not recommended.
Proof annotations
----------------------
-To process a proof asynchronously |Coq| needs to know the precise
+To process a proof asynchronously Coq needs to know the precise
statement of the theorem without looking at the proof. This requires
some annotations if the theorem is proved inside a Section (see
Section :ref:`section-mechanism`).
-When a section ends, |Coq| looks at the proof object to decide which
+When a section ends, Coq looks at the proof object to decide which
section variables are actually used and hence have to be quantified in
the statement of the theorem. To avoid making the construction of
proofs mandatory when ending a section, one can start each proof with
@@ -58,7 +58,7 @@ variables used.
Automatic suggestion of proof annotations
`````````````````````````````````````````
-The :flag:`Suggest Proof Using` flag makes |Coq| suggest, when a ``Qed``
+The :flag:`Suggest Proof Using` flag makes Coq suggest, when a ``Qed``
command is processed, a correct proof annotation. It is up to the user
to modify the proof script accordingly.
@@ -66,17 +66,17 @@ to modify the proof script accordingly.
Proof blocks and error resilience
--------------------------------------
-|Coq| 8.6 introduced a mechanism for error resilience: in interactive
-mode |Coq| is able to completely check a document containing errors
+Coq 8.6 introduced a mechanism for error resilience: in interactive
+mode Coq is able to completely check a document containing errors
instead of bailing out at the first failure.
Two kind of errors are supported: errors occurring in vernacular
commands and errors occurring in proofs.
-To properly recover from a failing tactic, |Coq| needs to recognize the
+To properly recover from a failing tactic, Coq needs to recognize the
structure of the proof in order to confine the error to a sub proof.
Proof block detection is performed by looking at the syntax of the
-proof script (i.e. also looking at indentation). |Coq| comes with four
+proof script (i.e. also looking at indentation). Coq comes with four
kind of proof blocks, and an ML API to add new ones.
:curly: blocks are delimited by { and }, see Chapter :ref:`proofhandling`
@@ -92,13 +92,13 @@ Caveats
When a vernacular command fails the subsequent error messages may be
bogus, i.e. caused by the first error. Error resilience for vernacular
commands can be switched off by passing ``-async-proofs-command-error-resilience off``
-to |CoqIDE|.
+to CoqIDE.
An incorrect proof block detection can result into an incorrect error
recovery and hence in bogus errors. Proof block detection cannot be
precise for bullets or any other non well parenthesized proof
structure. Error resilience can be turned off or selectively activated
-for any set of block kind passing to |CoqIDE| one of the following
+for any set of block kind passing to CoqIDE one of the following
options:
- ``-async-proofs-tactic-error-resilience off``
@@ -113,13 +113,13 @@ Interactive mode
---------------------
At the time of writing the only user interface supporting asynchronous
-proof processing is |CoqIDE|.
+proof processing is CoqIDE.
-When |CoqIDE| is started, two |Coq| processes are created. The master one
+When CoqIDE is started, two Coq processes are created. The master one
follows the user, giving feedback as soon as possible by skipping
proofs, which are delegated to the worker process. The worker process,
whose state can be seen by clicking on the button in the lower right
-corner of the main |CoqIDE| window, asynchronously processes the proofs.
+corner of the main CoqIDE window, asynchronously processes the proofs.
If a proof contains an error, it is reported in red in the label of
the very same button, that can also be used to see the list of errors
and jump to the corresponding line.
@@ -137,14 +137,14 @@ Only then all the universe constraints are checked.
Caveats
```````
-The number of worker processes can be increased by passing |CoqIDE|
+The number of worker processes can be increased by passing CoqIDE
the ``-async-proofs-j n`` flag. Note that the memory consumption increases too,
since each worker requires the same amount of memory as the master
process. Also note that increasing the number of workers may reduce
the reactivity of the master process to user commands.
To disable this feature, one can pass the ``-async-proofs off`` flag to
-|CoqIDE|. Conversely, on Windows, where the feature is disabled by
+CoqIDE. Conversely, on Windows, where the feature is disabled by
default, pass the ``-async-proofs on`` flag to enable it.
Proofs that are known to take little time to process are not delegated
@@ -166,9 +166,9 @@ Batch mode
a ``Require``. Indeed, the loading of a nonempty ``.vos`` file is
assigned higher priority than the loading of a ``.vio`` file.
-When |Coq| is used as a batch compiler by running ``coqc``, it produces
+When Coq is used as a batch compiler by running ``coqc``, it produces
a ``.vo`` file for each ``.v`` file. A ``.vo`` file contains, among other
-things, theorem statements and proofs. Hence to produce a .vo |Coq|
+things, theorem statements and proofs. Hence to produce a .vo Coq
need to process all the proofs of the ``.v`` file.
The asynchronous processing of proofs can decouple the generation of a
@@ -224,7 +224,7 @@ heavy use of the ``Type`` hierarchy.
Limiting the number of parallel workers
--------------------------------------------
-Many |Coq| processes may run on the same computer, and each of them may
+Many Coq processes may run on the same computer, and each of them may
start many additional worker processes. The ``coqworkmgr`` utility lets
one limit the number of workers, globally.
@@ -232,9 +232,9 @@ The utility accepts the ``-j`` argument to specify the maximum number of
workers (defaults to 2). ``coqworkmgr`` automatically starts in the
background and prints an environment variable assignment
like ``COQWORKMGR_SOCKET=localhost:45634``. The user must set this variable
-in all the shells from which |Coq| processes will be started. If one
+in all the shells from which Coq processes will be started. If one
uses just one terminal running the bash shell, then
``export ‘coqworkmgr -j 4‘`` will do the job.
-After that, all |Coq| processes, e.g. ``coqide`` and ``coqc``, will respect the
+After that, all Coq processes, e.g. ``coqide`` and ``coqc``, will respect the
limit, globally.
diff --git a/doc/sphinx/addendum/program.rst b/doc/sphinx/addendum/program.rst
index 5da1ac3f46..298ea4b4ab 100644
--- a/doc/sphinx/addendum/program.rst
+++ b/doc/sphinx/addendum/program.rst
@@ -8,25 +8,25 @@ Program
:Author: Matthieu Sozeau
We present here the |Program| tactic commands, used to build
-certified |Coq| programs, elaborating them from their algorithmic
+certified Coq programs, elaborating them from their algorithmic
skeleton and a rich specification :cite:`sozeau06`. It can be thought of as a
dual of :ref:`Extraction <extraction>`. The goal of |Program| is to
program as in a regular functional programming language whilst using
as rich a specification as desired and proving that the code meets the
-specification using the whole |Coq| proof apparatus. This is done using
+specification using the whole Coq proof apparatus. This is done using
a technique originating from the “Predicate subtyping” mechanism of
PVS :cite:`Rushby98`, which generates type checking conditions while typing a
term constrained to a particular type. Here we insert existential
variables in the term, which must be filled with proofs to get a
-complete |Coq| term. |Program| replaces the |Program| tactic by Catherine
+complete Coq term. |Program| replaces the |Program| tactic by Catherine
Parent :cite:`Parent95b` which had a similar goal but is no longer maintained.
-The languages available as input are currently restricted to |Coq|’s
-term language, but may be extended to |OCaml|, Haskell and
-others in the future. We use the same syntax as |Coq| and permit to use
+The languages available as input are currently restricted to Coq’s
+term language, but may be extended to OCaml, Haskell and
+others in the future. We use the same syntax as Coq and permit to use
implicit arguments and the existing coercion mechanism. Input terms
and types are typed in an extended system (Russell) and interpreted
-into |Coq| terms. The interpretation process may produce some proof
+into Coq terms. The interpretation process may produce some proof
obligations which need to be resolved to create the final term.
@@ -35,7 +35,7 @@ obligations which need to be resolved to create the final term.
Elaborating programs
--------------------
-The main difference from |Coq| is that an object in a type :g:`T : Set` can
+The main difference from Coq is that an object in a type :g:`T : Set` can
be considered as an object of type :g:`{x : T | P}` for any well-formed
:g:`P : Prop`. If we go from :g:`T` to the subset of :g:`T` verifying property
:g:`P`, we must prove that the object under consideration verifies it. Russell
@@ -86,7 +86,7 @@ coercions.
Controls the special treatment of pattern matching generating equalities
and disequalities when using |Program| (it is on by default). All
pattern-matches and let-patterns are handled using the standard algorithm
- of |Coq| (see :ref:`extendedpatternmatching`) when this flag is
+ of Coq (see :ref:`extendedpatternmatching`) when this flag is
deactivated.
.. flag:: Program Generalized Coercion
@@ -116,7 +116,7 @@ Syntactic control over equalities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To give more control over the generation of equalities, the
-type checker will fall back directly to |Coq|’s usual typing of dependent
+type checker will fall back directly to Coq’s usual typing of dependent
pattern matching if a ``return`` or ``in`` clause is specified. Likewise, the
if construct is not treated specially by |Program| so boolean tests in
the code are not automatically reflected in the obligations. One can
@@ -161,13 +161,13 @@ Program Definition
A :cmd:`Definition` command with the :attr:`program` attribute 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 :n:`@ident` in the environment.
+final Coq term to the name :n:`@ident` in the environment.
:n:`Program Definition @ident : @type := @term`
Interprets the type :n:`@type`, potentially generating proof
-obligations to be resolved. Once done with them, we have a |Coq|
-type :n:`@type__0`. It then elaborates the preterm :n:`@term` into a |Coq|
+obligations to be resolved. Once done with them, we have a Coq
+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`
@@ -342,7 +342,7 @@ Frequently Asked Questions
.. exn:: Ill-formed recursive definition.
This error can happen when one tries to define a function by structural
- recursion on a subset object, which means the |Coq| function looks like:
+ recursion on a subset object, which means the Coq function looks like:
::
diff --git a/doc/sphinx/addendum/ring.rst b/doc/sphinx/addendum/ring.rst
index da1a393b4a..c93d621048 100644
--- a/doc/sphinx/addendum/ring.rst
+++ b/doc/sphinx/addendum/ring.rst
@@ -10,8 +10,8 @@
.. _theringandfieldtacticfamilies:
-The ring and field tactic families
-====================================
+ring and field: solvers for polynomial and rational equations
+=============================================================
:Author: Bruno Barras, Benjamin Grégoire, Assia Mahboubi, Laurent Théry [#f1]_
@@ -99,7 +99,7 @@ Yes, building the variables map and doing the substitution after
normalizing is automatically done by the tactic. So you can just
forget this paragraph and use the tactic according to your intuition.
-Concrete usage in |Coq|
+Concrete usage in Coq
--------------------------
.. tacn:: ring {? [ {+ @one_term } ] }
@@ -382,7 +382,7 @@ The syntax for adding a new ring is
that, given a term, “abstracts” it into an object of type |N| whose
interpretation via ``Cp_phi`` (the evaluation function of power
coefficient) is the original term, or returns ``InitialRing.NotConstant``
- if not a constant coefficient (i.e. |L_tac| is the inverse function of
+ if not a constant coefficient (i.e. |Ltac| is the inverse function of
``Cp_phi``). See files ``plugins/ring/ZArithRing.v``
and ``plugins/ring/RealField.v`` for examples. By default the tactic
does not recognize power expressions as ring expressions.
@@ -429,10 +429,10 @@ How does it work?
The code of ``ring`` is a good example of a tactic written using *reflection*.
What is reflection? Basically, using it means that a part of a tactic is written
-in Gallina, |Coq|'s language of terms, rather than |Ltac| or |OCaml|. From the
+in Gallina, Coq's language of terms, rather than |Ltac| or OCaml. From the
philosophical point of view, reflection is using the ability of the Calculus of
Constructions to speak and reason about itself. For the ``ring`` tactic we used
-|Coq| as a programming language and also as a proof environment to build a tactic
+Coq as a programming language and also as a proof environment to build a tactic
and to prove its correctness.
The interested reader is strongly advised to have a look at the
@@ -491,7 +491,7 @@ its correctness w.r.t interpretation, that is:
So now, what is the scheme for a normalization proof? Let p be the
polynomial expression that the user wants to normalize. First a little
-piece of |ML| code guesses the type of `p`, the ring theory `T` to use, an
+piece of ML code guesses the type of `p`, the ring theory `T` to use, an
abstract polynomial `ap` and a variables map `v` such that `p` is |bdi|-
equivalent to `(PEeval v ap)`. Then we replace it by `(Pphi_dev v (norm ap))`,
using the main correctness theorem and we reduce it to a
@@ -567,6 +567,19 @@ Dealing with fields
intros x y H H1; field [H1]; auto.
Abort.
+
+.. example:: :tacn:`field` that generates side goals
+
+ .. coqtop:: reset all
+
+ Require Import Reals.
+ Goal forall x y:R,
+ (x * y > 0)%R ->
+ (x * (1 / x + x / (x + y)))%R =
+ ((- 1 / y) * y * (- x * (x / (x + y)) - 1))%R.
+
+ intros; field.
+
.. tacn:: field_simplify {? [ {+ @one_term__eq } ] } {+ @one_term } {? in @ident }
Performs the simplification in the conclusion of the
@@ -677,9 +690,9 @@ History of ring
First Samuel Boutin designed the tactic ``ACDSimpl``. This tactic did lot
of rewriting. But the proofs terms generated by rewriting were too big
-for |Coq|’s type checker. Let us see why:
+for Coq’s type checker. Let us see why:
-.. coqtop:: all
+.. coqtop:: reset all
Require Import ZArith.
Open Scope Z_scope.
@@ -697,7 +710,7 @@ was rewritten by Patrick Loiseleur: the new tactic does not any
more require ``ACDSimpl`` to compile and it makes use of |bdi|-reduction not
only to replace the rewriting steps, but also to achieve the
interleaving of computation and reasoning (see :ref:`discussion_reflection`). He also wrote
-some |ML| code for the ``Add Ring`` command that allows registering new rings dynamically.
+some ML code for the ``Add Ring`` command that allows registering new rings dynamically.
Proofs terms generated by ring are quite small, they are linear in the
number of :math:`\oplus` and :math:`\otimes` operations in the normalized terms. Type checking
@@ -740,12 +753,12 @@ tactics using reflection.
Another idea suggested by Benjamin Werner: reflection could be used to
couple an external tool (a rewriting program or a model checker)
-with |Coq|. We define (in |Coq|) a type of terms, a type of *traces*, and
+with Coq. We define (in Coq) a type of terms, a type of *traces*, and
prove a correctness theorem that states that *replaying traces* is safe
with respect to some interpretation. Then we let the external tool do every
computation (using side-effects, backtracking, exception, or others
features that are not available in pure lambda calculus) to produce
-the trace. Now we can check in |Coq| that the trace has the expected
+the trace. Now we can check in Coq that the trace has the expected
semantics by applying the correctness theorem.
diff --git a/doc/sphinx/addendum/sprop.rst b/doc/sphinx/addendum/sprop.rst
index 6c62ff3116..2b1f343e14 100644
--- a/doc/sphinx/addendum/sprop.rst
+++ b/doc/sphinx/addendum/sprop.rst
@@ -10,13 +10,13 @@ SProp (proof irrelevant propositions)
In particular, conversion checking through bytecode or native code
compilation currently does not understand proof irrelevance.
-This section describes the extension of |Coq| with definitionally
+This section describes the extension of Coq with definitionally
proof irrelevant propositions (types in the sort :math:`\SProp`, also
known as strict propositions) as described in
:cite:`Gilbert:POPL2019`.
Use of |SProp| may be disabled by passing ``-disallow-sprop`` to the
-|Coq| program or by turning the :flag:`Allow StrictProp` flag off.
+Coq program or by turning the :flag:`Allow StrictProp` flag off.
.. flag:: Allow StrictProp
:name: Allow StrictProp
diff --git a/doc/sphinx/addendum/type-classes.rst b/doc/sphinx/addendum/type-classes.rst
index 7638fce010..56d90b33d8 100644
--- a/doc/sphinx/addendum/type-classes.rst
+++ b/doc/sphinx/addendum/type-classes.rst
@@ -13,7 +13,7 @@ Class and Instance declarations
-------------------------------
The syntax for class and instance declarations is the same as the record
-syntax of |Coq|:
+syntax of Coq:
.. coqdoc::
@@ -61,7 +61,7 @@ Note that if you finish the proof with :cmd:`Qed` the entire instance
will be opaque, including the fields given in the initial term.
Alternatively, in :flag:`Program Mode` if one does not give all the
-members in the Instance declaration, |Coq| generates obligations for the
+members in the Instance declaration, Coq generates obligations for the
remaining fields, e.g.:
.. coqtop:: in
@@ -242,7 +242,7 @@ binders. For example:
Definition lt `{eqa : EqDec A, ! Ord eqa} (x y : A) := andb (le x y) (neqb x y).
The ``!`` modifier switches the way a binder is parsed back to the usual
-interpretation of |Coq|. In particular, it uses the implicit arguments
+interpretation of Coq. In particular, it uses the implicit arguments
mechanism if available, as shown in the example.
Substructures
@@ -336,20 +336,23 @@ Summary of the commands
.. cmd:: Instance {? @ident_decl {* @binder } } : @type {? @hint_info } {? {| := %{ {* @field_def } %} | := @term } }
- .. insertprodn hint_info hint_info
+ .. insertprodn hint_info one_pattern
.. prodn::
- hint_info ::= %| {? @natural } {? @one_term }
+ hint_info ::= %| {? @natural } {? @one_pattern }
+ one_pattern ::= @one_term
Declares a typeclass instance named
:token:`ident_decl` of the class :n:`@type` with the specified parameters and with
fields defined by :token:`field_def`, where each field must be a declared field of
the class.
- Add one or more :token:`binder`\s to declare a parameterized instance. :token:`hint_info`
- specifies the hint priority, where 0 is the highest priority as for
+ Adds one or more :token:`binder`\s to declare a parameterized instance. :token:`hint_info`
+ may be used to specify the hint priority, where 0 is the highest priority as for
:tacn:`auto` hints. If the priority is not specified, the default is the number
- of non-dependent binders of the instance.
+ of non-dependent binders of the instance. If :token:`one_pattern` is given, terms
+ matching that pattern will trigger use of the instance. Otherwise,
+ use is triggered based on the conclusion of the type.
This command supports the :attr:`global` attribute that can be
used on instances declared in a section so that their
@@ -513,7 +516,7 @@ Settings
This flag (off by default) respects the dependency order
between subgoals, meaning that subgoals on which other subgoals depend
come first, while the non-dependent subgoals were put before
- the dependent ones previously (|Coq| 8.5 and below). This can result in
+ the dependent ones previously (Coq 8.5 and below). This can result in
quite different performance behaviors of proof search.
diff --git a/doc/sphinx/addendum/universe-polymorphism.rst b/doc/sphinx/addendum/universe-polymorphism.rst
index dd26534ec7..1fb337b30a 100644
--- a/doc/sphinx/addendum/universe-polymorphism.rst
+++ b/doc/sphinx/addendum/universe-polymorphism.rst
@@ -12,7 +12,7 @@ General Presentation
The status of Universe Polymorphism is experimental.
-This section describes the universe polymorphic extension of |Coq|.
+This section describes the universe polymorphic extension of Coq.
Universe polymorphism makes it possible to write generic definitions
making use of universes and reuse them at different and sometimes
incompatible universe levels.
@@ -231,7 +231,7 @@ constraints by prefixing the level names with symbols.
Because inductive subtypings are only produced by comparing inductives
to themselves with universes changed, they amount to variance
information: each universe is either invariant, covariant or
-irrelevant (there are no contravariant subtypings in |Coq|),
+irrelevant (there are no contravariant subtypings in Coq),
respectively represented by the symbols `=`, `+` and `*`.
Here we see that :g:`list` binds an irrelevant universe, so any two
@@ -474,7 +474,7 @@ mode, introduced universe names can be referred to in terms. Note that
local universe names shadow global universe names. During a proof, one
can use :cmd:`Show Universes` to display the current context of universes.
-It is possible to provide only some universe levels and let |Coq| infer the others
+It is possible to provide only some universe levels and let Coq infer the others
by adding a :g:`+` in the list of bound universe levels:
.. coqtop:: all
diff --git a/doc/sphinx/appendix/history-and-changes/index.rst b/doc/sphinx/appendix/history-and-changes/index.rst
index b00a7cdb08..50ffec8e3f 100644
--- a/doc/sphinx/appendix/history-and-changes/index.rst
+++ b/doc/sphinx/appendix/history-and-changes/index.rst
@@ -5,10 +5,10 @@ History and recent changes
==========================
This chapter is divided in two parts. The first one is about the
-:ref:`early history of |Coq| <history>` and is presented in
+:ref:`early history of Coq <history>` and is presented in
chronological order. The second one provides :ref:`release notes
-about recent versions of |Coq| <changes>` and is presented in reverse
-chronological order. When updating your copy of |Coq| to a new version
+about recent versions of Coq <changes>` and is presented in reverse
+chronological order. When updating your copy of Coq to a new version
(especially a new major version), it is strongly recommended that you
read the corresponding release notes. They may contain advice that
will help you understand the differences with the previous version and
diff --git a/doc/sphinx/changes.rst b/doc/sphinx/changes.rst
index 5bc229954f..de5dbe79cc 100644
--- a/doc/sphinx/changes.rst
+++ b/doc/sphinx/changes.rst
@@ -14,7 +14,7 @@ Version 8.12
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.12 integrates many usability improvements,
+Coq version 8.12 integrates many usability improvements,
in particular with respect to notations, scopes and implicit arguments,
along with many bug fixes and major improvements to the reference manual.
The main changes include:
@@ -34,10 +34,10 @@ The main changes include:
this takes precedence over the now deprecated :ref:`ssreflect search<812SSRSearch>`.
- Many additions and improvements of the :ref:`standard library<812Stdlib>`.
- Improvements to the :ref:`reference manual<812Refman>` include a more logical organization
- of chapters along with updated syntax descriptions that match |Coq|'s grammar
+ of chapters along with updated syntax descriptions that match Coq's grammar
in most but not all chapters.
-Additionally, the :tacn:`omega` tactic is deprecated in this version of |Coq|,
+Additionally, the :tacn:`omega` tactic is deprecated in this version of Coq,
and we recommend users to switch to :tacn:`lia` in new proof scripts (see
also the warning message in the :ref:`corresponding chapter
<omega_chapter>`).
@@ -46,7 +46,7 @@ See the `Changes in 8.12+beta1`_ section and following sections for the
detailed list of changes, including potentially breaking changes marked
with **Changed**.
-|Coq|'s documentation is available at https://coq.github.io/doc/v8.12/refman (reference
+Coq's documentation is available at https://coq.github.io/doc/v8.12/refman (reference
manual), and https://coq.github.io/doc/v8.12/stdlib (documentation of
the standard library). Developer documentation of the ML API is available
at https://coq.github.io/doc/v8.12/api.
@@ -55,16 +55,16 @@ Maxime Dénès, Emilio Jesús Gallego Arias, Gaëtan Gilbert, Michael
Soegtrop and Théo Zimmermann worked on maintaining and improving the
continuous integration system and package building infrastructure.
-Erik Martin-Dorel has maintained the `|Coq| Docker images
-<https://hub.docker.com/r/coqorg/coq>`_ that are used in many |Coq|
+Erik Martin-Dorel has maintained the `Coq Docker images
+<https://hub.docker.com/r/coqorg/coq>`_ that are used in many Coq
projects for continuous integration.
-The OPAM repository for |Coq| packages has been maintained by
+The OPAM repository for Coq packages has been maintained by
Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with
contributions from many users. A list of packages is available at
https://coq.inria.fr/opam/www/.
-Previously, most components of |Coq| had a single principal maintainer.
+Previously, most components of Coq had a single principal maintainer.
This was changed in 8.12 (`#11295
<https://github.com/coq/coq/pull/11295>`_) so that every component now has
a team of maintainers, who are in charge of reviewing and
@@ -97,18 +97,18 @@ Laurent Théry, Ralf Treinen, Anton Trunov, Bernhard M. Wiedemann, Li-yao Xia,
Nickolai Zeldovich and Théo Zimmermann.
Many power users helped to improve the design of this new version via
-the GitHub issue and pull request system, the |Coq| development mailing list
+the GitHub issue and pull request system, the Coq development mailing list
coqdev@inria.fr, the coq-club@inria.fr mailing list, the `Discourse forum
-<https://coq.discourse.group/>`_ and the new `|Coq| Zulip chat <http://coq.zulipchat.com>`_
+<https://coq.discourse.group/>`_ and the new `Coq Zulip chat <http://coq.zulipchat.com>`_
(thanks to Cyril Cohen for organizing the move from Gitter).
Version 8.12's development spanned 6 months from the release of
-|Coq| 8.11.0. Emilio Jesus Gallego Arias and Théo Zimmermann are
-the release managers of |Coq| 8.12. This release is the result of
+Coq 8.11.0. Emilio Jesus Gallego Arias and Théo Zimmermann are
+the release managers of Coq 8.12. This release is the result of
~500 PRs merged, closing ~100 issues.
| Nantes, June 2020,
-| Matthieu Sozeau for the |Coq| development team
+| Matthieu Sozeau for the Coq development team
|
Changes in 8.12+beta1
@@ -131,7 +131,7 @@ Specification language, type inference
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- **Changed:**
- The deprecation warning raised since |Coq| 8.10 when a trailing
+ The deprecation warning raised since Coq 8.10 when a trailing
implicit is declared to be non-maximally inserted (with the command
:cmd:`Arguments`) has been turned into an error
(`#11368 <https://github.com/coq/coq/pull/11368>`_,
@@ -432,7 +432,7 @@ Tactics
fixes `#12210 <https://github.com/coq/coq/issues/12210>`_).
- **Fixed:**
:tacn:`zify` now handles :g:`Z.pow_pos` by default.
- In |Coq| 8.11, this was the case only when loading module
+ In Coq 8.11, this was the case only when loading module
:g:`ZifyPow` because this triggered a regression of :tacn:`lia`.
The regression is now fixed, and the module kept only for compatibility
(`#11362 <https://github.com/coq/coq/pull/11362>`_,
@@ -532,7 +532,7 @@ Flags, options and attributes
by Emilio Jesus Gallego Arias).
- **Removed:**
Unqualified ``polymorphic``, ``monomorphic``, ``template``,
- ``notemplate`` attributes (they were deprecated since |Coq| 8.10).
+ ``notemplate`` attributes (they were deprecated since Coq 8.10).
Use :attr:`universes(polymorphic)`, :attr:`universes(monomorphic)`,
:attr:`universes(template)` and :attr:`universes(notemplate)` instead
(`#11663 <https://github.com/coq/coq/pull/11663>`_, by Théo Zimmermann).
@@ -676,7 +676,7 @@ Tools
involving ``%``) (`#12126
<https://github.com/coq/coq/pull/12126>`_, by Jason Gross).
- **Changed:**
- When passing ``TIMED=1`` to ``make`` with either |Coq|'s own makefile
+ When passing ``TIMED=1`` to ``make`` with either Coq's own makefile
or a ``coq_makefile``\-made makefile, timing information is now
printed for OCaml files as well (`#12211
<https://github.com/coq/coq/pull/12211>`_, by Jason Gross).
@@ -701,7 +701,7 @@ Tools
<https://github.com/coq/coq/pull/12034>`_, by Gaëtan Gilbert).
- **Added:**
A new documentation environment ``details`` to make certain portion
- of a |Coq| document foldable. See :ref:`coqdoc-hide-show`
+ of a Coq document foldable. See :ref:`coqdoc-hide-show`
(`#10592 <https://github.com/coq/coq/pull/10592>`_,
by Thomas Letan).
- **Added:**
@@ -726,7 +726,7 @@ Tools
``--user``) to ``make`` (`#11302
<https://github.com/coq/coq/pull/11302>`_, by Jason Gross).
- **Added:**
- |Coq|'s build system now supports both ``TIMING_FUZZ``,
+ Coq's build system now supports both ``TIMING_FUZZ``,
``TIMING_SORT_BY``, and ``TIMING_REAL`` just like a ``Makefile``
made by ``coq_makefile`` (`#11302
<https://github.com/coq/coq/pull/11302>`_, by Jason Gross).
@@ -742,7 +742,7 @@ Tools
``TIMING_SORT_BY_MEM=1`` (to pass ``--sort-by-mem``) to ``make``
(`#11606 <https://github.com/coq/coq/pull/11606>`_, by Jason Gross).
- **Added:**
- |Coq|'s build system now supports both ``TIMING_INCLUDE_MEM`` and
+ Coq's build system now supports both ``TIMING_INCLUDE_MEM`` and
``TIMING_SORT_BY_MEM`` just like a ``Makefile`` made by
``coq_makefile`` (`#11606 <https://github.com/coq/coq/pull/11606>`_,
by Jason Gross).
@@ -765,7 +765,7 @@ Tools
(`#12091 <https://github.com/coq/coq/pull/12091>`_,
by Hugo Herbelin).
- **Fixed:**
- The various timing targets for |Coq|'s standard library now correctly
+ The various timing targets for Coq's standard library now correctly
display and label the "before" and "after" columns, rather than
mixing them up (`#11302 <https://github.com/coq/coq/pull/11302>`_
fixes `#11301 <https://github.com/coq/coq/issues/11301>`_, by Jason
@@ -799,15 +799,15 @@ Tools
<https://github.com/coq/coq/pull/12388>`_, fixes `#12387
<https://github.com/coq/coq/pull/12387>`_, by Jason Gross).
-|CoqIDE|
+CoqIDE
^^^^^^^^
- **Removed:**
- "Tactic" menu from |CoqIDE| which had been unmaintained for a number of years
+ "Tactic" menu from CoqIDE which had been unmaintained for a number of years
(`#11414 <https://github.com/coq/coq/pull/11414>`_,
by Pierre-Marie Pédrot).
- **Removed:**
- "Revert all buffers" command from |CoqIDE| which had been broken for a long time
+ "Revert all buffers" command from CoqIDE which had been broken for a long time
(`#11415 <https://github.com/coq/coq/pull/11415>`_,
by Pierre-Marie Pédrot).
@@ -1038,7 +1038,7 @@ Extraction
- **Added:**
Support for better extraction of strings in OCaml and Haskell:
- `ExtOcamlNativeString` provides bindings from the |Coq| `String` type to
+ `ExtOcamlNativeString` provides bindings from the Coq `String` type to
the OCaml `string` type, and string literals can be extracted to literals,
both in OCaml and Haskell (`#10486
<https://github.com/coq/coq/pull/10486>`_, by Xavier Leroy, with help from
@@ -1063,7 +1063,7 @@ Reference manual
organization. In the new version, there are fewer top-level
chapters, and, in the HTML format, chapters are split into smaller
pages. This is still a work in progress and further restructuring
- is expected in the next versions of |Coq|
+ is expected in the next versions of Coq
(`CEP#43 <https://github.com/coq/ceps/pull/43>`_, implemented in
`#11601 <https://github.com/coq/coq/pull/11601>`_,
`#11871 <https://github.com/coq/coq/pull/11871>`_,
@@ -1076,7 +1076,7 @@ Reference manual
help and reviews of Jim Fehrle, Clément Pit-Claudel and others).
- **Changed:**
Most of the grammar is now presented using the notation mechanism
- that has been used to present commands and tactics since |Coq| 8.8 and
+ that has been used to present commands and tactics since Coq 8.8 and
which is documented in :ref:`syntax-conventions`
(`#11183 <https://github.com/coq/coq/pull/11183>`_,
`#11314 <https://github.com/coq/coq/pull/11314>`_,
@@ -1141,9 +1141,6 @@ Infrastructure and dependencies
Changes in 8.12.0
~~~~~~~~~~~~~~~~~~~~~
-.. contents::
- :local:
-
**Notations**
- **Added:**
@@ -1201,9 +1198,9 @@ Changes in 8.12.0
fixes `#11970 <https://github.com/coq/coq/issues/11970>`_,
by Pierre-Marie Pédrot).
-**|CoqIDE|**
+**CoqIDE**
-- **Fixed:** |CoqIDE| no longer exits when trying to open a file whose name is not a valid identifier
+- **Fixed:** CoqIDE no longer exits when trying to open a file whose name is not a valid identifier
(`#12562 <https://github.com/coq/coq/pull/12562>`_,
fixes `#10988 <https://github.com/coq/coq/issues/10988>`_,
by Vincent Laporte).
@@ -1216,13 +1213,136 @@ Changes in 8.12.0
modified in the meantime (`#12583 <https://github.com/coq/coq/pull/12583>`_,
fixes `#12582 <https://github.com/coq/coq/issues/12582>`_, by Jason Gross).
+Changes in 8.12.1
+~~~~~~~~~~~~~~~~~~~~~
+
+**Kernel**
+
+- **Fixed:** Incompleteness of conversion checking on problems
+ involving :ref:`eta-expansion` and :ref:`cumulative universe
+ polymorphic inductive types <cumulative>` (`#12738
+ <https://github.com/coq/coq/pull/12738>`_, fixes `#7015
+ <https://github.com/coq/coq/issues/7015>`_, by Gaëtan Gilbert).
+
+- **Fixed:**
+ Polymorphic side-effects inside monomorphic definitions were incorrectly
+ handled as not inlined. This allowed deriving an inconsistency
+ (`#13331 <https://github.com/coq/coq/pull/13331>`_,
+ fixes `#13330 <https://github.com/coq/coq/issues/13330>`_,
+ by Pierre-Marie Pédrot).
+
+**Notations**
+
+- **Fixed:**
+ Undetected collision between a lonely notation and a notation in
+ scope at printing time
+ (`#12946 <https://github.com/coq/coq/pull/12946>`_,
+ fixes the first part of `#12908 <https://github.com/coq/coq/issues/12908>`_,
+ by Hugo Herbelin).
+- **Fixed:**
+ Printing of notations in custom entries with
+ variables not mentioning an explicit level
+ (`#13026 <https://github.com/coq/coq/pull/13026>`_,
+ fixes `#12775 <https://github.com/coq/coq/issues/12775>`_
+ and `#13018 <https://github.com/coq/coq/issues/13018>`_,
+ by Hugo Herbelin).
+
+**Tactics**
+
+- **Added:**
+ :tacn:`replace` and :tacn:`inversion` support registration of a
+ :g:`core.identity`\-like equality in :g:`Type`, such as HoTT's :g:`path`
+ (`#12847 <https://github.com/coq/coq/pull/12847>`_,
+ partially fixes `#12846 <https://github.com/coq/coq/issues/12846>`_,
+ by Hugo Herbelin).
+- **Fixed:**
+ Anomaly with :tacn:`injection` involving artificial
+ dependencies disappearing by reduction
+ (`#12816 <https://github.com/coq/coq/pull/12816>`_,
+ fixes `#12787 <https://github.com/coq/coq/issues/12787>`_,
+ by Hugo Herbelin).
+
+**Tactic language**
+
+- **Fixed:**
+ Miscellaneous issues with locating tactic errors
+ (`#13247 <https://github.com/coq/coq/pull/13247>`_,
+ fixes `#12773 <https://github.com/coq/coq/issues/12773>`_
+ and `#12992 <https://github.com/coq/coq/issues/12992>`_,
+ by Hugo Herbelin).
+
+**SSReflect**
+
+- **Fixed:**
+ Regression in error reporting after :tacn:`case <case (ssreflect)>`.
+ A generic error message "Could not fill dependent hole in apply" was
+ reported for any error following :tacn:`case <case (ssreflect)>` or
+ :tacn:`elim <elim (ssreflect)>`
+ (`#12857 <https://github.com/coq/coq/pull/12857>`_,
+ fixes `#12837 <https://github.com/coq/coq/issues/12837>`_,
+ by Enrico Tassi).
+
+**Commands and options**
+
+- **Fixed:**
+ Failures of :cmd:`Search` in the presence of primitive projections
+ (`#13301 <https://github.com/coq/coq/pull/13301>`_,
+ fixes `#13298 <https://github.com/coq/coq/issues/13298>`_,
+ by Hugo Herbelin).
+- **Fixed:**
+ :cmd:`Search` supports filtering on parts of identifiers which are
+ not proper identifiers themselves, such as :n:`"1"`
+ (`#13351 <https://github.com/coq/coq/pull/13351>`_,
+ fixes `#13349 <https://github.com/coq/coq/issues/13349>`_,
+ by Hugo Herbelin).
+
+**Tools**
+
+- **Fixed:**
+ Special symbols now escaped in the index produced by coqdoc,
+ avoiding collision with the syntax of the output format
+ (`#12754 <https://github.com/coq/coq/pull/12754>`_,
+ fixes `#12752 <https://github.com/coq/coq/issues/12752>`_,
+ by Hugo Herbelin).
+- **Fixed:**
+ The `details` environment added in the 8.12 release can now be used
+ as advertised in the reference manual
+ (`#12772 <https://github.com/coq/coq/pull/12772>`_,
+ by Thomas Letan).
+- **Fixed:**
+ Targets such as ``print-pretty-timed`` in ``coq_makefile``\-made
+ ``Makefile``\s no longer error in rare cases where ``--output-sync`` is not
+ passed to make and the timing output gets interleaved in just the wrong way
+ (`#13063 <https://github.com/coq/coq/pull/13063>`_, fixes `#13062
+ <https://github.com/coq/coq/issues/13062>`_, by Jason Gross).
+
+**CoqIDE**
+
+- **Fixed:**
+ View menu "Display parentheses"
+ (`#12794 <https://github.com/coq/coq/pull/12794>`_ and `#13067 <https://github.com/coq/coq/pull/13067>`_,
+ fixes `#12793 <https://github.com/coq/coq/issues/12793>`_,
+ by Jean-Christophe Léchenet and Hugo Herbelin).
+
+**Infrastructure and dependencies**
+
+- **Added:**
+ Coq is now tested against OCaml 4.11.1
+ (`#12972 <https://github.com/coq/coq/pull/12972>`_,
+ by Emilio Jesus Gallego Arias).
+- **Fixed:**
+ The reference manual can now build with Sphinx 3
+ (`#13011 <https://github.com/coq/coq/pull/13011>`_,
+ fixes `#12332 <https://github.com/coq/coq/issues/12332>`_,
+ by Théo Zimmermann and Jim Fehrle).
+
Version 8.11
------------
Summary of changes
~~~~~~~~~~~~~~~~~~
-The main changes brought by |Coq| version 8.11 are:
+The main changes brought by Coq version 8.11 are:
- :ref:`Ltac2<811Ltac2>`, a new tactic language for writing more robust larger scale
tactics, with built-in support for datatypes and the multi-goal tactic monad.
@@ -1250,17 +1370,17 @@ The main changes brought by |Coq| version 8.11 are:
instances of the constructive and classical real numbers.
Additionally, while the :tacn:`omega` tactic is not yet deprecated in
-this version of |Coq|, it should soon be the case and we already
+this version of Coq, it should soon be the case and we already
recommend users to switch to :tacn:`lia` in new proof scripts (see
also the warning message in the :ref:`corresponding chapter
<omega_chapter>`).
The ``dev/doc/critical-bugs`` file documents the known critical bugs
-of |Coq| and affected releases. See the `Changes in 8.11+beta1`_
+of Coq and affected releases. See the `Changes in 8.11+beta1`_
section and following sections for the detailed list of changes,
including potentially breaking changes marked with **Changed**.
-|Coq|'s documentation is available at https://coq.github.io/doc/v8.11/api (documentation of
+Coq's documentation is available at https://coq.github.io/doc/v8.11/api (documentation of
the ML API), https://coq.github.io/doc/v8.11/refman (reference
manual), and https://coq.github.io/doc/v8.11/stdlib (documentation of
the standard library).
@@ -1269,7 +1389,7 @@ Maxime Dénès, Emilio Jesús Gallego Arias, Gaëtan Gilbert, Michael
Soegtrop and Théo Zimmermann worked on maintaining and improving the
continuous integration system and package building infrastructure.
-The OPAM repository for |Coq| packages has been maintained by
+The OPAM repository for Coq packages has been maintained by
Guillaume Claret, Karl Palmskog, Matthieu Sozeau and Enrico Tassi with
contributions from many users. A list of packages is available at
https://coq.inria.fr/opam/www/.
@@ -1292,20 +1412,20 @@ Matthieu Sozeau, spanjel, Claude Stolze, Enrico Tassi, Laurent Théry,
James R. Wilcox, Xia Li-yao, Théo Zimmermann
Many power users helped to improve the design of the new features via
-the issue and pull request system, the |Coq| development mailing list,
+the issue and pull request system, the Coq development mailing list,
the coq-club@inria.fr mailing list or the `Discourse forum
<https://coq.discourse.group/>`_. It would be impossible to mention
exhaustively the names of everybody who to some extent influenced the
development.
-Version 8.11 is the sixth release of |Coq| developed on a time-based
+Version 8.11 is the sixth release of Coq developed on a time-based
development cycle. Its development spanned 3 months from the release of
-|Coq| 8.10. Pierre-Marie Pédrot is the release manager and maintainer of this
+Coq 8.10. Pierre-Marie Pédrot is the release manager and maintainer of this
release, assisted by Matthieu Sozeau. This release is the result of 2000+
commits and 300+ PRs merged, closing 75+ issues.
| Paris, November 2019,
-| Matthieu Sozeau for the |Coq| development team
+| Matthieu Sozeau for the Coq development team
|
@@ -1322,7 +1442,7 @@ Changes in 8.11+beta1
computation. Primitive floats are added in the language of terms,
following the binary64 format of the IEEE 754 standard, and the
related operations are implemented for the different reduction
- engines of |Coq| by using the corresponding processor operators in
+ engines of Coq by using the corresponding processor operators in
rounding-to-nearest-even. The properties of these operators are
axiomatized in the theory :g:`Coq.Floats.FloatAxioms` which is part
of the library :g:`Coq.Floats.Floats`.
@@ -1415,7 +1535,7 @@ Changes in 8.11+beta1
Output of the :cmd:`Print` and :cmd:`About` commands.
Arguments meta-data is now displayed as the corresponding
:cmd:`Arguments` command instead of the
- human-targeted prose used in previous |Coq| versions. (`#10985
+ human-targeted prose used in previous Coq versions. (`#10985
<https://github.com/coq/coq/pull/10985>`_, by Gaëtan Gilbert).
.. _811RefineInstance:
@@ -1514,7 +1634,7 @@ Changes in 8.11+beta1
- **Added:**
Ltac2, a new version of the tactic language Ltac, that doesn't
- preserve backward compatibility, has been integrated in the main |Coq|
+ preserve backward compatibility, has been integrated in the main Coq
distribution. It is still experimental, but we already recommend
users of advanced Ltac to start using it and report bugs or request
enhancements. See its documentation in the :ref:`dedicated chapter
@@ -1543,14 +1663,14 @@ Changes in 8.11+beta1
Generalize tactics :tacn:`under` and :tacn:`over` for any registered
relation. More precisely, assume the given context lemma has type
`forall f1 f2, .. -> (forall i, R1 (f1 i) (f2 i)) -> R2 f1 f2`. The
- first step performed by :tacn:`under` (since |Coq| 8.10) amounts to
+ first step performed by :tacn:`under` (since Coq 8.10) amounts to
calling the tactic :tacn:`rewrite <rewrite (ssreflect)>`, which
itself relies on :tacn:`setoid_rewrite` if need be. So this step was
already compatible with a double implication or setoid equality for
the conclusion head symbol `R2`. But a further step consists in
tagging the generated subgoal `R1 (f1 i) (?f2 i)` to protect it from
unwanted evar instantiation, and get `Under_rel _ R1 (f1 i) (?f2 i)`
- that is displayed as ``'Under[ f1 i ]``. In |Coq| 8.10, this second
+ that is displayed as ``'Under[ f1 i ]``. In Coq 8.10, this second
(convenience) step was only performed when `R1` was Leibniz' `eq` or
`iff`. Now, it is also performed for any relation `R1` which has a
``RewriteRelation`` instance (a `RelationClasses.Reflexive` instance
@@ -1612,7 +1732,7 @@ Changes in 8.11+beta1
.. warning::
This is a common source of incompatibilities in projects
- migrating to |Coq| 8.11.
+ migrating to Coq 8.11.
- **Changed:**
Output generated by :flag:`Printing Dependent Evars Line` flag
@@ -1643,7 +1763,7 @@ Changes in 8.11+beta1
`coqc` now provides the ability to generate compiled interfaces.
Use `coqc -vos foo.v` to skip all opaque proofs during the
compilation of `foo.v`, and output a file called `foo.vos`.
- This feature is experimental. It enables working on a |Coq| file without the need to
+ This feature is experimental. It enables working on a Coq file without the need to
first compile the proofs contained in its dependencies
(`#8642 <https://github.com/coq/coq/pull/8642>`_ by Arthur Charguéraud, review by
Maxime Dénès and Emilio Gallego).
@@ -1715,7 +1835,7 @@ Changes in 8.11+beta1
**Infrastructure and dependencies**
- **Changed:**
- |Coq| now officially supports OCaml 4.08.
+ Coq now officially supports OCaml 4.08.
See `INSTALL` file for details
(`#10471 <https://github.com/coq/coq/pull/10471>`_,
by Emilio Jesús Gallego Arias).
@@ -1793,7 +1913,7 @@ Changes in 8.11.0
**Tactic language**
- **Fixed:**
- Syntax of tactic `cofix ... with ...` was broken since |Coq| 8.10
+ Syntax of tactic `cofix ... with ...` was broken since Coq 8.10
(`#11241 <https://github.com/coq/coq/pull/11241>`_,
by Hugo Herbelin).
@@ -1826,9 +1946,9 @@ Changes in 8.11.0
fixes `#11353 <https://github.com/coq/coq/issues/11353>`_,
by Karl Palmskog).
-**|CoqIDE|**
+**CoqIDE**
-- **Changed:** |CoqIDE| now uses the GtkSourceView native implementation
+- **Changed:** CoqIDE now uses the GtkSourceView native implementation
of the autocomplete mechanism (`#11400
<https://github.com/coq/coq/pull/11400>`_, by Pierre-Marie Pédrot).
@@ -1874,7 +1994,7 @@ Changes in 8.11.1
(`#11859 <https://github.com/coq/coq/pull/11859>`_,
by Pierre Roux).
-**|CoqIDE|**
+**CoqIDE**
- **Fixed:**
Compiling file paths containing spaces
@@ -1932,21 +2052,21 @@ Changes in 8.11.2
(`#12070 <https://github.com/coq/coq/pull/12070>`_,
by Pierre Roux).
-**|CoqIDE|**
+**CoqIDE**
- **Changed:**
- |CoqIDE| now uses native window frames by default on Windows.
+ CoqIDE now uses native window frames by default on Windows.
The GTK window frames can be restored by setting the `GTK_CSD` environment variable to `1`
(`#12060 <https://github.com/coq/coq/pull/12060>`_,
fixes `#11080 <https://github.com/coq/coq/issues/11080>`_,
by Attila Gáspár).
- **Fixed:**
- New patch presumably fixing the random |Coq| 8.11 segfault issue with |CoqIDE| completion
+ New patch presumably fixing the random Coq 8.11 segfault issue with CoqIDE completion
(`#12068 <https://github.com/coq/coq/pull/12068>`_,
by Hugo Herbelin, presumably fixing
`#11943 <https://github.com/coq/coq/pull/11943>`_).
- **Fixed:**
- Highlighting style consistently applied to all three buffers of |CoqIDE|
+ Highlighting style consistently applied to all three buffers of CoqIDE
(`#12106 <https://github.com/coq/coq/pull/12106>`_,
by Hugo Herbelin; fixes
`#11506 <https://github.com/coq/coq/pull/11506>`_).
@@ -1957,7 +2077,7 @@ Version 8.10
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.10 contains two major new features: support for a native
+Coq version 8.10 contains two major new features: support for a native
fixed-precision integer type and a new sort :math:`\SProp` of strict
propositions. It is also the result of refinements and stabilization of
previous features, deprecations or removals of deprecated features,
@@ -2058,15 +2178,15 @@ reference manual. Here are the most important user-visible changes:
:math:`\Type`. It used to be limited to sort `Prop`
(`#7634 <https://github.com/coq/coq/pull/7634>`_, by Théo Winterhalter).
-- A new registration mechanism for reference from ML code to |Coq|
+- A new registration mechanism for reference from ML code to Coq
constructs has been added
(`#186 <https://github.com/coq/coq/pull/186>`_,
by Emilio Jesús Gallego Arias, Maxime Dénès and Vincent Laporte).
-- |CoqIDE|:
+- CoqIDE:
- - |CoqIDE| now depends on gtk+3 and lablgtk3 instead of gtk+2 and lablgtk2.
- The INSTALL file available in the |Coq| sources has been updated to list
+ - CoqIDE now depends on gtk+3 and lablgtk3 instead of gtk+2 and lablgtk2.
+ The INSTALL file available in the Coq sources has been updated to list
the new dependencies
(`#9279 <https://github.com/coq/coq/pull/9279>`_,
by Hugo Herbelin, with help from Jacques Garrigue,
@@ -2081,15 +2201,15 @@ reference manual. Here are the most important user-visible changes:
- Infrastructure and dependencies:
- - |Coq| 8.10 requires OCaml >= 4.05.0, bumped from 4.02.3 See the
+ - Coq 8.10 requires OCaml >= 4.05.0, bumped from 4.02.3 See the
`INSTALL` file for more information on dependencies
(`#7522 <https://github.com/coq/coq/pull/7522>`_, by Emilio Jesús Gallego Arías).
- - |Coq| 8.10 doesn't need Camlp5 to build anymore. It now includes a
- fork of the core parsing library that |Coq| uses, which is a small
+ - Coq 8.10 doesn't need Camlp5 to build anymore. It now includes a
+ fork of the core parsing library that Coq uses, which is a small
subset of the whole Camlp5 distribution. In particular, this subset
doesn't depend on the OCaml AST, allowing easier compilation and
- testing on experimental OCaml versions. |Coq| also ships a new parser
+ testing on experimental OCaml versions. Coq also ships a new parser
`coqpp` that plugin authors must switch to
(`#7902 <https://github.com/coq/coq/pull/7902>`_,
`#7979 <https://github.com/coq/coq/pull/7979>`_,
@@ -2098,19 +2218,19 @@ reference manual. Here are the most important user-visible changes:
and `#8945 <https://github.com/coq/coq/pull/8945>`_,
by Pierre-Marie Pédrot and Emilio Jesús Gallego Arias).
- The |Coq| developers would like to thank Daniel de Rauglaudre for many
+ The Coq developers would like to thank Daniel de Rauglaudre for many
years of continued support.
- - |Coq| now supports building with Dune, in addition to the traditional
+ - Coq now supports building with Dune, in addition to the traditional
Makefile which is scheduled for deprecation
(`#6857 <https://github.com/coq/coq/pull/6857>`_,
by Emilio Jesús Gallego Arias, with help from Rudi Grinberg).
- Experimental support for building |Coq| projects has been integrated
+ Experimental support for building Coq projects has been integrated
in Dune at the same time, providing an `improved experience
<https://coq.discourse.group/t/a-guide-to-building-your-coq-libraries-and-plugins-with-dune/>`_
for plugin developers. We thank the Dune team for their work
- supporting |Coq|.
+ supporting Coq.
Version 8.10 also comes with a bunch of smaller-scale changes and
improvements regarding the different components of the system, including
@@ -2121,7 +2241,7 @@ the numerous changes to the implementation and improvements of
interfaces. The file provides guidelines on porting a plugin to the new
version and a plugin development tutorial originally made by Yves Bertot
is now in `doc/plugin_tutorial`. The ``dev/doc/critical-bugs`` file
-documents the known critical bugs of |Coq| and affected releases.
+documents the known critical bugs of Coq and affected releases.
The efficiency of the whole system has seen improvements thanks to
contributions from Gaëtan Gilbert, Pierre-Marie Pédrot, and Maxime Dénès.
@@ -2129,16 +2249,16 @@ contributions from Gaëtan Gilbert, Pierre-Marie Pédrot, and Maxime Dénès.
Maxime Dénès, Emilio Jesús Gallego Arias, Gaëtan Gilbert, Michael
Soegtrop, Théo Zimmermann worked on maintaining and improving the
continuous integration system and package building infrastructure.
-|Coq| is now continuously tested against the |OCaml| trunk, in addition to the
+Coq is now continuously tested against the OCaml trunk, in addition to the
oldest supported and latest OCaml releases.
-|Coq|'s documentation for the development branch is now deployed
+Coq's documentation for the development branch is now deployed
continuously at https://coq.github.io/doc/master/api (documentation of
the ML API), https://coq.github.io/doc/master/refman (reference
manual), and https://coq.github.io/doc/master/stdlib (documentation of
the standard library). Similar links exist for the `v8.10` branch.
-The OPAM repository for |Coq| packages has been maintained by Guillaume
+The OPAM repository for Coq packages has been maintained by Guillaume
Melquiond, Matthieu Sozeau, Enrico Tassi (who migrated it to opam 2)
with contributions from many users. A list of packages is available at
https://coq.inria.fr/opam/www/.
@@ -2160,19 +2280,19 @@ Tassi, Laurent Théry, Kamil Trzciński, whitequark, Théo Winterhalter,
Xia Li-yao, Beta Ziliani and Théo Zimmermann.
Many power users helped to improve the design of the new features via
-the issue and pull request system, the |Coq| development mailing list,
+the issue and pull request system, the Coq development mailing list,
the coq-club@inria.fr mailing list or the new Discourse forum. It would
be impossible to mention exhaustively the names of everybody who to some
extent influenced the development.
-Version 8.10 is the fifth release of |Coq| developed on a time-based
+Version 8.10 is the fifth release of Coq developed on a time-based
development cycle. Its development spanned 6 months from the release of
-|Coq| 8.9. Vincent Laporte is the release manager and maintainer of this
+Coq 8.9. Vincent Laporte is the release manager and maintainer of this
release. This release is the result of ~2500 commits and ~650 PRs merged,
closing 150+ issues.
| Santiago de Chile, April 2019,
-| Matthieu Sozeau for the |Coq| development team
+| Matthieu Sozeau for the Coq development team
|
Other changes in 8.10+beta1
@@ -2191,13 +2311,13 @@ Other changes in 8.10+beta1
(*à la* ``-top``) based on the filename passed, taking into account the
proper ``-R``/``-Q`` options. For example, given ``-R Foo foolib`` using
``-topfile foolib/bar.v`` will set the module name to ``Foo.Bar``.
- |CoqIDE| now properly sets the module name for a given file based on
+ CoqIDE now properly sets the module name for a given file based on
its path
(`#8991 <https://github.com/coq/coq/pull/8991>`_,
closes `#8989 <https://github.com/coq/coq/issues/8989>`_,
by Gaëtan Gilbert).
- - Experimental: |Coq| flags and options can now be set on the
+ - Experimental: Coq flags and options can now be set on the
command-line, e.g. ``-set "Universe Polymorphism=true"``
(`#9876 <https://github.com/coq/coq/pull/9876>`_, by Gaëtan Gilbert).
@@ -2295,7 +2415,7 @@ Other changes in 8.10+beta1
- Deprecated compatibility notations have actually been
removed. Uses of these notations are generally easy to fix thanks
- to the hint contained in the deprecation warning emitted by |Coq|
+ to the hint contained in the deprecation warning emitted by Coq
8.8 and 8.9. For projects that require more than a handful of
such fixes, there is `a script
<https://gist.github.com/JasonGross/9770653967de3679d131c59d42de6d17#file-replace-notations-py>`_
@@ -2310,7 +2430,7 @@ Other changes in 8.10+beta1
- The `quote plugin
<https://coq.inria.fr/distrib/V8.9.0/refman/proof-engine/detailed-tactic-examples.html#quote>`_
was removed. If some users are interested in maintaining this plugin
- externally, the |Coq| development team can provide assistance for
+ externally, the Coq development team can provide assistance for
extracting the plugin and setting up a new repository
(`#7894 <https://github.com/coq/coq/pull/7894>`_, by Maxime Dénès).
@@ -2537,7 +2657,7 @@ Other changes in 8.10+beta1
- Changelog has been moved from a specific file `CHANGES.md` to the
reference manual; former Credits chapter of the reference manual has
been split in two parts: a History chapter which was enriched with
- additional historical information about |Coq| versions 1 to 5, and a
+ additional historical information about Coq versions 1 to 5, and a
Changes chapter which was enriched with the content formerly in
`CHANGES.md` and `COMPATIBILITY`
(`#9133 <https://github.com/coq/coq/pull/9133>`_,
@@ -2580,15 +2700,15 @@ Many bug fixes and documentation improvements, in particular:
fixes `#9336 <https://github.com/coq/coq/issues/9336>`_,
by Andreas Lynge, review by Enrico Tassi)
-**|CoqIDE|**
+**CoqIDE**
-- Fix |CoqIDE| instability on Windows after the update to gtk3
+- Fix CoqIDE instability on Windows after the update to gtk3
(`#10360 <https://github.com/coq/coq/pull/10360>`_, by Michael Soegtrop,
closes `#9885 <https://github.com/coq/coq/issues/9885>`_).
**Miscellaneous**
-- Proof General can now display |Coq|-generated diffs between proof steps
+- Proof General can now display Coq-generated diffs between proof steps
in color
(`#10019 <https://github.com/coq/coq/pull/10019>`_ and
(in Proof General) `#421 <https://github.com/ProofGeneral/PG/pull/421>`_,
@@ -2696,7 +2816,7 @@ A few bug fixes and documentation improvements, in particular:
fixes `#10894 <https://github.com/coq/coq/issues/10894>`_,
by Hugo Herbelin).
-**|CoqIDE|**
+**CoqIDE**
- Fix handling of unicode input before space
(`#10852 <https://github.com/coq/coq/pull/10852>`_,
@@ -2736,9 +2856,9 @@ Changes in 8.10.2
(`#11090 <https://github.com/coq/coq/pull/11090>`_,
fixes `#11033 <https://github.com/coq/coq/issues/11033>`_, by Hugo Herbelin).
-**|CoqIDE|**
+**CoqIDE**
-- Fixed uneven dimensions of |CoqIDE| panels when window has been resized
+- Fixed uneven dimensions of CoqIDE panels when window has been resized
(`#11070 <https://github.com/coq/coq/pull/11070>`_,
fixes 8.10-regression `#10956 <https://github.com/coq/coq/issues/10956>`_,
by Guillaume Melquiond).
@@ -2761,7 +2881,7 @@ Version 8.9
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.9 contains the result of refinements and stabilization
+Coq version 8.9 contains the result of refinements and stabilization
of features and deprecations or removals of deprecated features,
cleanups of the internals of the system and API along with a few new
features. This release includes many user-visible changes, including
@@ -2779,7 +2899,7 @@ changes:
manual).
- Deprecated notations of the standard library will be removed in the
- next version of |Coq|, see the next subsection for a script to
+ next version of Coq, see the next subsection for a script to
ease porting, by Jason Gross and Jean-Christophe Léchenet.
- Added the :cmd:`Number Notation` command for registering decimal
@@ -2842,7 +2962,7 @@ changes:
- Tools: removed the ``gallina`` utility and the homebrewed ``Emacs`` mode.
-- Packaging: as in |Coq| 8.8.2, the Windows installer now includes many
+- Packaging: as in Coq 8.8.2, the Windows installer now includes many
more external packages that can be individually selected for
installation, by Michael Soegtrop.
@@ -2853,10 +2973,10 @@ important ones are documented in the next subsection file.
On the implementation side, the ``dev/doc/changes.md`` file documents
the numerous changes to the implementation and improvements of
interfaces. The file provides guidelines on porting a plugin to the new
-version and a plugin development tutorial kept in sync with |Coq| was
+version and a plugin development tutorial kept in sync with Coq was
introduced by Yves Bertot http://github.com/ybertot/plugin_tutorials.
The new ``dev/doc/critical-bugs`` file documents the known critical bugs
-of |Coq| and affected releases.
+of Coq and affected releases.
The efficiency of the whole system has seen improvements thanks to
contributions from Gaëtan Gilbert, Pierre-Marie Pédrot, and Maxime Dénès.
@@ -2865,7 +2985,7 @@ Maxime Dénès, Emilio Jesús Gallego Arias, Gaëtan Gilbert, Michael
Soegtrop, Théo Zimmermann worked on maintaining and improving the
continuous integration system.
-The OPAM repository for |Coq| packages has been maintained by Guillaume
+The OPAM repository for Coq packages has been maintained by Guillaume
Melquiond, Matthieu Sozeau, Enrico Tassi with contributions from many
users. A list of packages is available at https://coq.inria.fr/opam/www/.
@@ -2885,23 +3005,23 @@ Tassi, Laurent Théry, Anton Trunov, whitequark, Théo Winterhalter,
Zeimer, Beta Ziliani, Théo Zimmermann.
Many power users helped to improve the design of the new features via
-the issue and pull request system, the |Coq| development mailing list or
+the issue and pull request system, the Coq development mailing list or
the coq-club@inria.fr mailing list. It would be impossible to mention
exhaustively the names of everybody who to some extent influenced the
development.
-Version 8.9 is the fourth release of |Coq| developed on a time-based
+Version 8.9 is the fourth release of Coq developed on a time-based
development cycle. Its development spanned 7 months from the release of
-|Coq| 8.8. The development moved to a decentralized merging process
+Coq 8.8. The development moved to a decentralized merging process
during this cycle. Guillaume Melquiond was in charge of the release
process and is the maintainer of this release. This release is the
result of ~2,000 commits and ~500 PRs merged, closing 75+ issues.
-The |Coq| development team welcomed Vincent Laporte, a new |Coq|
-engineer working with Maxime Dénès in the |Coq| consortium.
+The Coq development team welcomed Vincent Laporte, a new Coq
+engineer working with Maxime Dénès in the Coq consortium.
| Paris, November 2018,
-| Matthieu Sozeau for the |Coq| development team
+| Matthieu Sozeau for the Coq development team
|
Details of changes in 8.9+beta1
@@ -2917,7 +3037,7 @@ Notations
entries" (see chapter "Syntax extensions" of the reference manual).
- Deprecated compatibility notations will actually be removed in the
- next version of |Coq|. Uses of these notations are generally easy to
+ next version of Coq. Uses of these notations are generally easy to
fix thanks to the hint contained in the deprecation warnings. For
projects that require more than a handful of such fixes, there is `a
script
@@ -3018,7 +3138,7 @@ Standard Library
- Numeral syntax for `nat` is no longer available without loading the
entire prelude (`Require Import Coq.Init.Prelude`). This only
- impacts users running |Coq| without the init library (`-nois` or
+ impacts users running Coq without the init library (`-nois` or
`-noinit`) and also issuing `Require Import Coq.Init.Datatypes`.
Tools
@@ -3028,10 +3148,10 @@ Tools
`COQFLAGS` is now entirely separate from `COQLIBS`, so in custom Makefiles
`$(COQFLAGS)` should be replaced by `$(COQFLAGS) $(COQLIBS)`.
-- Removed the `gallina` utility (extracts specification from |Coq| vernacular files).
+- Removed the `gallina` utility (extracts specification from Coq vernacular files).
If you would like to maintain this tool externally, please contact us.
-- Removed the Emacs modes distributed with |Coq|. You are advised to
+- Removed the Emacs modes distributed with Coq. You are advised to
use `Proof-General <https://proofgeneral.github.io/>`_ (and optionally
`Company-Coq <https://github.com/cpitclaudel/company-coq>`_) instead.
If your use case is not covered by these alternative Emacs modes,
@@ -3060,15 +3180,15 @@ Vernacular Commands
NoTCResolution`.
- Multiple sections with the same name are allowed.
-|Coq| binaries and process model
+Coq binaries and process model
-- Before 8.9, |Coq| distributed a single `coqtop` binary and a set of
+- Before 8.9, Coq distributed a single `coqtop` binary and a set of
dynamically loadable plugins that used to take over the main loop
for tasks such as IDE language server or parallel proof checking.
These plugins have been turned into full-fledged binaries so each
different process has associated a particular binary now, in
- particular `coqidetop` is the |CoqIDE| language server, and
+ particular `coqidetop` is the CoqIDE language server, and
`coq{proof,tactic,query}worker` are in charge of task-specific and
parallel proof checking.
@@ -3126,7 +3246,7 @@ Changes in 8.8.1
- Some quality-of-life fixes.
- Numerous improvements to the documentation.
- Fix a critical bug related to primitive projections and :tacn:`native_compute`.
-- Ship several additional |Coq| libraries with the Windows installer.
+- Ship several additional Coq libraries with the Windows installer.
Version 8.8
-----------
@@ -3134,7 +3254,7 @@ Version 8.8
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.8 contains the result of refinements and stabilization of
+Coq version 8.8 contains the result of refinements and stabilization of
features and deprecations, cleanups of the internals of the system along
with a few new features. The main user visible changes are:
@@ -3196,12 +3316,12 @@ contributions from Gaëtan Gilbert, Pierre-Marie Pédrot, Maxime Dénès and
Matthieu Sozeau and performance issue tracking by Jason Gross and Paul
Steckler.
-The official wiki and the bugtracker of |Coq| migrated to the GitHub
+The official wiki and the bugtracker of Coq migrated to the GitHub
platform, thanks to the work of Pierre Letouzey and Théo
Zimmermann. Gaëtan Gilbert, Emilio Jesús Gallego Arias worked on
maintaining and improving the continuous integration system.
-The OPAM repository for |Coq| packages has been maintained by Guillaume
+The OPAM repository for Coq packages has been maintained by Guillaume
Melquiond, Matthieu Sozeau, Enrico Tassi with contributions from many
users. A list of packages is available at https://coq.inria.fr/opam/www/.
@@ -3216,26 +3336,26 @@ Clément Pit-Claudel, Matthew Ryan, Matt Quinn, Sigurd Schneider, Bernhard
Schommer, Michael Soegtrop, Matthieu Sozeau, Arnaud Spiwack, Paul Steckler,
Enrico Tassi, Anton Trunov, Martin Vassor, Vadim Zaliva and Théo Zimmermann.
-Version 8.8 is the third release of |Coq| developed on a time-based
+Version 8.8 is the third release of Coq developed on a time-based
development cycle. Its development spanned 6 months from the release of
-|Coq| 8.7 and was based on a public roadmap. The development process
+Coq 8.7 and was based on a public roadmap. The development process
was coordinated by Matthieu Sozeau. Maxime Dénès was in charge of the
release process. Théo Zimmermann is the maintainer of this release.
Many power users helped to improve the design of the new features via
-the bug tracker, the pull request system, the |Coq| development mailing
+the bug tracker, the pull request system, the Coq development mailing
list or the coq-club@inria.fr mailing list. Special thanks to the users who
contributed patches and intensive brain-storming and code reviews,
starting with Jason Gross, Ralf Jung, Robbert Krebbers and Amin Timany.
It would however be impossible to mention exhaustively the names
of everybody who to some extent influenced the development.
-The |Coq| consortium, an organization directed towards users and
+The Coq consortium, an organization directed towards users and
supporters of the system, is now running and employs Maxime Dénès.
-The contacts of the |Coq| Consortium are Yves Bertot and Maxime Dénès.
+The contacts of the Coq Consortium are Yves Bertot and Maxime Dénès.
| Santiago de Chile, March 2018,
-| Matthieu Sozeau for the |Coq| development team
+| Matthieu Sozeau for the Coq development team
|
Details of changes in 8.8+beta1
@@ -3354,7 +3474,7 @@ Universes
Tools
-- |Coq| can now be run with the option -mangle-names to change the auto-generated
+- Coq can now be run with the option -mangle-names to change the auto-generated
name scheme. This is intended to function as a linter for developments that
want to be robust to changes in auto-generated names. This feature is experimental,
and may change or disappear without warning.
@@ -3364,7 +3484,7 @@ Checker
- The checker now accepts filenames in addition to logical paths.
-|CoqIDE|
+CoqIDE
- Find and Replace All report the number of occurrences found; Find indicates
when it wraps.
@@ -3377,7 +3497,7 @@ coqdep
Documentation
-- The |Coq| FAQ, formerly located at https://coq.inria.fr/faq, has been
+- The Coq FAQ, formerly located at https://coq.inria.fr/faq, has been
moved to the GitHub wiki section of this repository; the main entry
page is https://github.com/coq/coq/wiki/The-Coq-FAQ.
- Documentation: a large community effort resulted in the migration
@@ -3427,7 +3547,7 @@ Details of changes in 8.8.0
Tools
- Asynchronous proof delegation policy was fixed. Since version 8.7
- |Coq| was ignoring previous runs and the `-async-proofs-delegation-threshold`
+ Coq was ignoring previous runs and the `-async-proofs-delegation-threshold`
option did not have the expected behavior.
Tactic language
@@ -3501,7 +3621,7 @@ Version 8.7
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.7 contains the result of refinements, stabilization of features
+Coq version 8.7 contains the result of refinements, stabilization of features
and cleanups of the internals of the system along with a few new features. The
main user visible changes are:
@@ -3520,7 +3640,7 @@ main user visible changes are:
and the extensibility of generated Makefiles, and to make ``_CoqProject`` files
more palatable to IDEs by Enrico Tassi.
-|Coq| 8.7 involved a large amount of work on cleaning and speeding up the code
+Coq 8.7 involved a large amount of work on cleaning and speeding up the code
base, notably the work of Pierre-Marie Pédrot on making the tactic-level system
insensitive to existential variable expansion, providing a safer API to plugin
writers and making the code more robust. The ``dev/doc/changes.txt`` file
@@ -3540,7 +3660,7 @@ Thomas Sibut-Pinote and Hugo Herbelin added support for side effect hooks in
cbv, cbn and simpl. The side effects are provided via a plugin available at
https://github.com/herbelin/reduction-effects/.
-The BigN, BigZ, BigQ libraries are no longer part of the |Coq| standard library,
+The BigN, BigZ, BigQ libraries are no longer part of the Coq standard library,
they are now provided by a separate repository https://github.com/coq/bignums,
maintained by Pierre Letouzey.
@@ -3554,7 +3674,7 @@ others, documented in the next subsection file.
The mathematical proof language/declarative mode plugin was removed from the
archive.
-The OPAM repository for |Coq| packages has been maintained by Guillaume Melquiond,
+The OPAM repository for Coq packages has been maintained by Guillaume Melquiond,
Matthieu Sozeau, Enrico Tassi with contributions from many users. A list of
packages is available at https://coq.inria.fr/opam/www/.
@@ -3579,29 +3699,29 @@ Maxime Dénès, who was also in charge of the release process. Théo Zimmermann
the maintainer of this release.
Many power users helped to improve the design of the new features via the bug
-tracker, the pull request system, the |Coq| development mailing list or the
+tracker, the pull request system, the Coq development mailing list or the
Coq-Club mailing list. Special thanks to the users who contributed patches and
intensive brain-storming and code reviews, starting with Jason Gross, Ralf Jung,
Robbert Krebbers, Xavier Leroy, Clément Pit–Claudel and Gabriel Scherer. It
would however be impossible to mention exhaustively the names of everybody who
to some extent influenced the development.
-Version 8.7 is the second release of |Coq| developed on a time-based development
-cycle. Its development spanned 9 months from the release of |Coq| 8.6 and was
+Version 8.7 is the second release of Coq developed on a time-based development
+cycle. Its development spanned 9 months from the release of Coq 8.6 and was
based on a public road-map. It attracted many external contributions. Code
reviews and continuous integration testing were systematically used before
integration of new features, with an important focus given to compatibility and
-performance issues, resulting in a hopefully more robust release than |Coq| 8.6
+performance issues, resulting in a hopefully more robust release than Coq 8.6
while maintaining compatibility.
-|Coq| Enhancement Proposals (CEPs for short) and open pull request discussions
+Coq Enhancement Proposals (CEPs for short) and open pull request discussions
were used to discuss publicly the new features.
-The |Coq| consortium, an organization directed towards users and supporters of the
+The Coq consortium, an organization directed towards users and supporters of the
system, is now upcoming and will rely on Inria’s newly created Foundation.
| Paris, August 2017,
-| Matthieu Sozeau and the |Coq| development team
+| Matthieu Sozeau and the Coq development team
|
Potential compatibility issues
@@ -3700,7 +3820,7 @@ Vernacular Commands
- Possibility to unset the printing of notations in a more fine grained
fashion than `Unset Printing Notations` is provided without any
user-syntax. The goal is that someone creates a plugin to experiment
- such a user-syntax, to be later integrated in |Coq| when stabilized.
+ such a user-syntax, to be later integrated in Coq when stabilized.
- `About` now tells if a reference is a coercion.
- The deprecated `Save` vernacular and its form `Save Theorem id` to
close proofs have been removed from the syntax. Please use `Qed`.
@@ -3718,7 +3838,7 @@ Standard Library
- New lemmas about iff and about orders on positive and Z.
- New lemmas on powerRZ.
- Strengthened statement of JMeq_eq_dep (closes bug #4912).
-- The BigN, BigZ, BigZ libraries are no longer part of the |Coq| standard
+- The BigN, BigZ, BigZ libraries are no longer part of the Coq standard
library, they are now provided by a separate repository
https://github.com/coq/bignums
The split has been done just after the Int31 library.
@@ -3732,12 +3852,12 @@ Standard Library
Plugins
-- The Ssreflect plugin is now distributed with |Coq|. Its documentation has
+- The Ssreflect plugin is now distributed with Coq. Its documentation has
been integrated as a chapter of the reference manual. This chapter is
work in progress so feedback is welcome.
- The mathematical proof language (also known as declarative mode) was removed.
- A new command Extraction TestCompile has been introduced, not meant
- for the general user but instead for |Coq|'s test-suite.
+ for the general user but instead for Coq's test-suite.
- The extraction plugin is no longer loaded by default. It must be
explicitly loaded with [Require Extraction], which is backwards
compatible.
@@ -3756,7 +3876,7 @@ Tools
the extensibility of generated Makefiles, and to make _CoqProject files
more palatable to IDEs. Overview:
- * _CoqProject files contain only |Coq| specific data (i.e. the list of
+ * _CoqProject files contain only Coq specific data (i.e. the list of
files, -R options, ...)
* coq_makefile translates _CoqProject to Makefile.conf and copies in the
desired location a standard Makefile (that reads Makefile.conf)
@@ -3814,15 +3934,15 @@ Details of changes in 8.7+beta2
Tools
-- In |CoqIDE|, the "Compile Buffer" command takes account of flags in
+- In CoqIDE, the "Compile Buffer" command takes account of flags in
_CoqProject or other project file.
Improvements around some error messages.
Many bug fixes including two important ones:
-- Bug #5730: |CoqIDE| becomes unresponsive on file open.
-- coq_makefile: make sure compile flags for |Coq| and coq_makefile are in sync
+- Bug #5730: CoqIDE becomes unresponsive on file open.
+- coq_makefile: make sure compile flags for Coq and coq_makefile are in sync
(in particular, make sure the `-safe-string` option is used to compile plugins).
Details of changes in 8.7.0
@@ -3833,7 +3953,7 @@ OCaml
- Users can pass specific flags to the OCaml optimizing compiler by
-using the flambda-opts configure-time option.
- Beware that compiling |Coq| with a flambda-enabled compiler is
+ Beware that compiling Coq with a flambda-enabled compiler is
experimental and may require large amounts of RAM and CPU, see
INSTALL for more details.
@@ -3863,7 +3983,7 @@ Version 8.6
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.6 contains the result of refinements, stabilization of
+Coq version 8.6 contains the result of refinements, stabilization of
8.5’s features and cleanups of the internals of the system. Over the
year of (now time-based) development, about 450 bugs were resolved and
over 100 contributions integrated. The main user visible changes are:
@@ -3871,9 +3991,9 @@ over 100 contributions integrated. The main user visible changes are:
- A new, faster state-of-the-art universe constraint checker, by
Jacques-Henri Jourdan.
-- In |CoqIDE| and other asynchronous interfaces, more fine-grained
+- In CoqIDE and other asynchronous interfaces, more fine-grained
asynchronous processing and error reporting by Enrico Tassi, making
- |Coq| capable of recovering from errors and continue processing the
+ Coq capable of recovering from errors and continue processing the
document.
- More access to the proof engine features from Ltac: goal management
@@ -3897,7 +4017,7 @@ over 100 contributions integrated. The main user visible changes are:
- Integration of LtacProf, a profiler for Ltac by Jason Gross, Paul
Steckler, Enrico Tassi and Tobias Tebbi.
-|Coq| 8.6 also comes with a bunch of smaller-scale changes and
+Coq 8.6 also comes with a bunch of smaller-scale changes and
improvements regarding the different components of the system. We shall
only list a few of them.
@@ -3920,7 +4040,7 @@ Matthieu Sozeau. The minimization algorithm has been improved by
Matthieu Sozeau.
The unifier has been improved by Hugo Herbelin and Matthieu Sozeau,
-fixing some incompatibilities introduced in |Coq| 8.5. Unification
+fixing some incompatibilities introduced in Coq 8.5. Unification
constraints can now be left floating around and be seen by the user
thanks to a new option. The Keyed Unification mode has been improved by
Matthieu Sozeau.
@@ -3943,19 +4063,19 @@ the pretty-printing and user interface communication components.
Frédéric Besson maintained the micromega tactic.
-The OPAM repository for |Coq| packages has been maintained by Guillaume
+The OPAM repository for Coq packages has been maintained by Guillaume
Claret, Guillaume Melquiond, Matthieu Sozeau, Enrico Tassi and others. A
list of packages is now available at https://coq.inria.fr/opam/www/.
Packaging tools and software development kits were prepared by Michael
Soegtrop with the help of Maxime Dénès and Enrico Tassi for Windows, and
Maxime Dénès and Matthieu Sozeau for MacOS X. Packages are now regularly
-built on the continuous integration server. |Coq| now comes with a META
+built on the continuous integration server. Coq now comes with a META
file usable with ocamlfind, contributed by Emilio Jesús Gallego Arias,
Gregory Malecha, and Matthieu Sozeau.
Matej Košík maintained and greatly improved the continuous integration
-setup and the testing of |Coq| contributions. He also contributed many API
+setup and the testing of Coq contributions. He also contributed many API
improvements and code cleanups throughout the system.
The contributors for this version are Bruno Barras, C.J. Bell, Yves
@@ -3972,7 +4092,7 @@ coordinated by Hugo Herbelin and Matthieu Sozeau with the help of Maxime
Dénès, who was also in charge of the release process.
Many power users helped to improve the design of the new features via
-the bug tracker, the pull request system, the |Coq| development mailing
+the bug tracker, the pull request system, the Coq development mailing
list or the Coq-Club mailing list. Special thanks to the users who
contributed patches and intensive brain-storming and code reviews,
starting with Cyril Cohen, Jason Gross, Robbert Krebbers, Jonathan
@@ -3981,23 +4101,23 @@ Scherer and Beta Ziliani. It would however be impossible to mention
exhaustively the names of everybody who to some extent influenced the
development.
-Version 8.6 is the first release of |Coq| developed on a time-based
+Version 8.6 is the first release of Coq developed on a time-based
development cycle. Its development spanned 10 months from the release of
-|Coq| 8.5 and was based on a public roadmap. To date, it contains more
-external contributions than any previous |Coq| system. Code reviews were
+Coq 8.5 and was based on a public roadmap. To date, it contains more
+external contributions than any previous Coq system. Code reviews were
systematically done before integration of new features, with an
important focus given to compatibility and performance issues, resulting
-in a hopefully more robust release than |Coq| 8.5.
+in a hopefully more robust release than Coq 8.5.
-|Coq| Enhancement Proposals (CEPs for short) were introduced by Enrico
+Coq Enhancement Proposals (CEPs for short) were introduced by Enrico
Tassi to provide more visibility and a discussion period on new
features, they are publicly available https://github.com/coq/ceps.
Started during this period, an effort is led by Yves Bertot and Maxime
-Dénès to put together a |Coq| consortium.
+Dénès to put together a Coq consortium.
| Paris, November 2016,
-| Matthieu Sozeau and the |Coq| development team
+| Matthieu Sozeau and the Coq development team
|
Potential sources of incompatibilities
@@ -4134,13 +4254,13 @@ General infrastructure
- New configurable warning system which can be controlled with the vernacular
command "Set Warnings", or, under coqc/coqtop, with the flag "-w". In
particular, the default is now that warnings are printed by coqc.
-- In asynchronous mode, |Coq| is now capable of recovering from errors and
+- In asynchronous mode, Coq is now capable of recovering from errors and
continue processing the document.
Tools
- coqc accepts a -o option to specify the output file name
-- coqtop accepts --print-version to print |Coq| and |OCaml| versions in
+- coqtop accepts --print-version to print Coq and OCaml versions in
easy to parse format
- Setting [Printing Dependent Evars Line] can be unset to disable the
computation associated with printing the "dependent evars: " line in
@@ -4169,7 +4289,7 @@ Other bug fixes in universes, type class shelving,...
Details of changes in 8.6.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Fix #5380: Default colors for |CoqIDE| are actually applied.
+- Fix #5380: Default colors for CoqIDE are actually applied.
- Fix plugin warnings
- Document named evars (including Show ident)
- Fix Bug #5574, document function scope
@@ -4221,7 +4341,7 @@ Version 8.5
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.5 contains the result of five specific long-term projects:
+Coq version 8.5 contains the result of five specific long-term projects:
- A new asynchronous evaluation and compilation mode by Enrico Tassi
with help from Bruno Barras and Carst Tankink.
@@ -4252,7 +4372,7 @@ the backtracking behavior of tactics. Multiple goal handling paves the
way for smarter automation tactics. It is currently used for simple goal
manipulation such as goal reordering.
-The way |Coq| processes a document in batch and interactive mode has been
+The way Coq processes a document in batch and interactive mode has been
redesigned by Enrico Tassi with help from Bruno Barras. Opaque proofs,
the text between Proof and Qed, can be processed asynchronously,
decoupling the checking of definitions and statements from the checking
@@ -4265,12 +4385,12 @@ already Required. All .vio files can be turned into complete .vo files
in parallel. The same infrastructure also allows terminating tactics to
be run in parallel on a set of goals via the ``par:`` goal selector.
-|CoqIDE| was modified to cope with asynchronous checking of the document.
-Its source code was also made separate from that of |Coq|, so that |CoqIDE|
+CoqIDE was modified to cope with asynchronous checking of the document.
+Its source code was also made separate from that of Coq, so that CoqIDE
no longer has a special status among user interfaces, paving the way for
-decoupling its release cycle from that of |Coq| in the future.
+decoupling its release cycle from that of Coq in the future.
-Carst Tankink developed a |Coq| back-end for user interfaces built on
+Carst Tankink developed a Coq back-end for user interfaces built on
Makarius Wenzel’s Prover IDE framework (PIDE), like PIDE/jEdit (with
help from Makarius Wenzel) or PIDE/Coqoon (with help from Alexander
Faithfull and Jesper Bengtson). The development of such features was
@@ -4304,7 +4424,7 @@ principles such as propositional extensionality and univalence, thanks
to Maxime Dénès and Bruno Barras. To ensure compatibility with the
univalence axiom, a new flag ``-indices-matter`` has been implemented,
taking into account the universe levels of indices when computing the
-levels of inductive types. This supports using |Coq| as a tool to explore
+levels of inductive types. This supports using Coq as a tool to explore
the relations between homotopy theory and type theory.
Maxime Dénès and Benjamin Grégoire developed an implementation of
@@ -4312,7 +4432,7 @@ conversion test and normal form computation using the OCaml native
compiler. It complements the virtual machine conversion offering much
faster computation for expensive functions.
-|Coq| 8.5 also comes with a bunch of many various smaller-scale changes
+Coq 8.5 also comes with a bunch of many various smaller-scale changes
and improvements regarding the different components of the system. We
shall only list a few of them.
@@ -4334,13 +4454,13 @@ Matthieu Sozeau. Error messages for unification and type inference
failures have been improved by Hugo Herbelin, Pierre-Marie Pédrot and
Arnaud Spiwack.
-Pierre Courtieu contributed new features for using |Coq| through Proof
+Pierre Courtieu contributed new features for using Coq through Proof
General and for better interactive experience (bullets, Search, etc).
The efficiency of the whole system has been significantly improved
thanks to contributions from Pierre-Marie Pédrot.
-A distribution channel for |Coq| packages using the OPAM tool has been
+A distribution channel for Coq packages using the OPAM tool has been
initiated by Thomas Braibant and developed by Guillaume Claret, with
contributions by Enrico Tassi and feedback from Hugo Herbelin.
@@ -4357,7 +4477,7 @@ Jonathan Leivent, Greg Malecha, Clément Pit-Claudel, Marc Lasson, Lionel
Rieg. It would however be impossible to mention with precision all names
of people who to some extent influenced the development.
-Version 8.5 is one of the most important releases of |Coq|. Its development
+Version 8.5 is one of the most important releases of Coq. Its development
spanned over about 3 years and a half with about one year of
beta-testing. General maintenance during part or whole of this period
has been done by Pierre Boutillier, Pierre Courtieu, Maxime Dénès, Hugo
@@ -4369,14 +4489,14 @@ Mahboubi, Jean-Marc Notin, Yann Régis-Gianas, François Ripault, Carst
Tankink. Maxime Dénès coordinated the release process.
| Paris, January 2015, revised December 2015,
-| Hugo Herbelin, Matthieu Sozeau and the |Coq| development team
+| Hugo Herbelin, Matthieu Sozeau and the Coq development team
|
Potential sources of incompatibilities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-List of typical changes to be done to adapt files from |Coq| 8.4
-to |Coq| 8.5 when not using compatibility option ``-compat 8.4``.
+List of typical changes to be done to adapt files from Coq 8.4
+to Coq 8.5 when not using compatibility option ``-compat 8.4``.
- Symptom: "The reference omega was not found in the current environment".
@@ -4511,7 +4631,7 @@ Logic
logic inconsistent).
- The guard condition for fixpoints is now a bit stricter. Propagation
of subterm value through pattern matching is restricted according to
- the return predicate. Restores compatibility of |Coq|'s logic with the
+ the return predicate. Restores compatibility of Coq's logic with the
propositional extensionality axiom. May create incompatibilities in
recursive programs heavily using dependent types.
- Trivial inductive types are no longer defined in Type but in Prop, which
@@ -4551,7 +4671,7 @@ Vernacular commands
- A new Print Strategies command allows visualizing the opacity status
of the whole engine.
- The "Locate" command now searches through all sorts of qualified namespaces of
- |Coq|: terms, modules, tactics, etc. The old behavior of the command can be
+ Coq: terms, modules, tactics, etc. The old behavior of the command can be
retrieved using the "Locate Term" command.
- New "Derive" command to help writing program by derivation.
- New "Refine Instance Mode" option that allows to deactivate the generation of
@@ -4879,24 +4999,24 @@ Tools
files from the quickly generated proofs.
- The XML plugin was discontinued and removed from the source.
- A new utility called coqworkmgr can be used to limit the number of
- concurrent workers started by independent processes, like make and |CoqIDE|.
+ concurrent workers started by independent processes, like make and CoqIDE.
This is of interest for users of the par: goal selector.
Interfaces
-- |CoqIDE| supports asynchronous edition of the document, ongoing tasks and
+- CoqIDE supports asynchronous edition of the document, ongoing tasks and
errors are reported in the bottom right window. The number of workers
taking care of processing proofs can be selected with -async-proofs-j.
-- |CoqIDE| highlights in yellow "unsafe" commands such as axiom
+- CoqIDE highlights in yellow "unsafe" commands such as axiom
declarations, and tactics like "give_up".
-- |CoqIDE| supports Proof General like key bindings;
+- CoqIDE supports Proof General like key bindings;
to activate the PG mode go to Edit -> Preferences -> Editor.
For the documentation see Help -> Help for PG mode.
-- |CoqIDE| automatically retracts the locked area when one edits the
+- CoqIDE automatically retracts the locked area when one edits the
locked text.
-- |CoqIDE| search and replace got regular expressions power. See the
+- CoqIDE search and replace got regular expressions power. See the
documentation of OCaml's Str module for the supported syntax.
-- Many |CoqIDE| windows, including the query one, are now detachable to
+- Many CoqIDE windows, including the query one, are now detachable to
improve usability on multi screen work stations.
- Coqtop/coqc outputs highlighted syntax. Colors can be configured thanks
to the COQ_COLORS environment variable, and their current state can
@@ -4907,7 +5027,7 @@ Interfaces
Internal Infrastructure
- Many reorganizations in the ocaml source files. For instance,
- many internal a.s.t. of |Coq| are now placed in mli files in
+ many internal a.s.t. of Coq are now placed in mli files in
a new directory intf/, for instance constrexpr.mli or glob_term.mli.
More details in dev/doc/changes.
@@ -4959,7 +5079,7 @@ Tactics
Extraction
- Definitions extracted to Haskell GHC should no longer randomly
- segfault when some |Coq| types cannot be represented by Haskell types.
+ segfault when some Coq types cannot be represented by Haskell types.
- Definitions can now be extracted to Json for post-processing.
Tools
@@ -5057,8 +5177,8 @@ Tools
Standard Library
- There is now a Coq.Compat.Coq84 library, which sets the various compatibility
- options and does a few redefinitions to make |Coq| behave more like |Coq| v8.4.
- The standard way of putting |Coq| in v8.4 compatibility mode is to pass the command
+ options and does a few redefinitions to make Coq behave more like Coq v8.4.
+ The standard way of putting Coq in v8.4 compatibility mode is to pass the command
line flags "-require Coq.Compat.Coq84 -compat 8.4".
Details of changes in 8.5
@@ -5067,7 +5187,7 @@ Details of changes in 8.5
Tools
- Flag "-compat 8.4" now loads Coq.Compat.Coq84. The standard way of
- putting |Coq| in v8.4 compatibility mode is to pass the command line flag
+ putting Coq in v8.4 compatibility mode is to pass the command line flag
"-compat 8.4". It can be followed by "-require Coq.Compat.AdmitAxiom"
if the 8.4 behavior of admit is needed, in which case it uses an axiom.
@@ -5108,7 +5228,7 @@ Various performance improvements (time, space used by .vo files)
Other bugfixes
- Fix order of arguments to Big.compare_case in ExtrOcamlZBigInt.v
-- Added compatibility coercions from Specif.v which were present in |Coq| 8.4.
+- Added compatibility coercions from Specif.v which were present in Coq 8.4.
- Fixing a source of inefficiency and an artificial dependency in the printer in the congruence tactic.
- Allow to unset the refinement mode of Instance in ML
- Fixing an incorrect use of prod_appvect on a term which was not a product in setoid_rewrite.
@@ -5123,7 +5243,7 @@ Other bugfixes
- #4623: set tactic too weak with universes (regression)
- Fix incorrect behavior of CS resolution
- #4591: Uncaught exception in directory browsing.
-- |CoqIDE| is more resilient to initialization errors.
+- CoqIDE is more resilient to initialization errors.
- #4614: "Fully check the document" is uninterruptible.
- Try eta-expansion of records only on non-recursive ones
- Fix bug when a sort is ascribed to a Record
@@ -5133,23 +5253,23 @@ Other bugfixes
- Fix strategy of Keyed Unification
- #4608: Anomaly "output_value: abstract value (outside heap)".
- #4607: do not read native code files if native compiler was disabled.
-- #4105: poor escaping in the protocol between |CoqIDE| and coqtop.
+- #4105: poor escaping in the protocol between CoqIDE and coqtop.
- #4596: [rewrite] broke in the past few weeks.
- #4533 (partial): respect declared global transparency of projections in unification.ml
- #4544: Backtrack on using full betaiota reduction during keyed unification.
-- #4540: |CoqIDE| bottom progress bar does not update.
+- #4540: CoqIDE bottom progress bar does not update.
- Fix regression from 8.4 in reflexivity
- #4580: [Set Refine Instance Mode] also used for Program Instance.
- #4582: cannot override notation [ x ]. MAY CREATE INCOMPATIBILITIES, see #4683.
- STM: Print/Extraction have to be skipped if -quick
-- #4542: |CoqIDE|: STOP button also stops workers
+- #4542: CoqIDE: STOP button also stops workers
- STM: classify some variants of Instance as regular `` `Fork `` nodes.
- #4574: Anomaly: Uncaught exception Invalid_argument("splay_arity").
- Do not give a name to anonymous evars anymore. See bug #4547.
- STM: always stock in vio files the first node (state) of a proof
- STM: not delegate proofs that contain Vernac(Module|Require|Import), #4530
- Don't fail fatally if PATH is not set.
-- #4537: |Coq| 8.5 is slower in typeclass resolution.
+- #4537: Coq 8.5 is slower in typeclass resolution.
- #4522: Incorrect "Warning..." on windows.
- #4373: coqdep does not know about .vio files.
- #3826: "Incompatible module types" is uninformative.
@@ -5158,7 +5278,7 @@ Other bugfixes
- #4503: mixing universe polymorphic and monomorphic variables and definitions in sections is unsupported.
- #4519: oops, global shadowed local universe level bindings.
- #4506: Anomaly: File "pretyping/indrec.ml", line 169, characters 14-20: Assertion failed.
-- #4548: |CoqIDE| crashes when going back one command
+- #4548: CoqIDE crashes when going back one command
Details of changes in 8.5pl2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -5179,8 +5299,8 @@ Other bugfixes
- #4644: a regression in unification.
- #4725: Function (Error: Conversion test raised an anomaly) and Program
(Error: Cannot infer this placeholder of type)
-- #4747: Problem building |Coq| 8.5pl1 with OCaml 4.03.0: Fatal warnings
-- #4752: |CoqIDE| crash on files not ended by ".v".
+- #4747: Problem building Coq 8.5pl1 with OCaml 4.03.0: Fatal warnings
+- #4752: CoqIDE crash on files not ended by ".v".
- #4777: printing inefficiency with implicit arguments
- #4818: "Admitted" fails due to undefined universe anomaly after calling
"destruct"
@@ -5194,7 +5314,7 @@ Other bugfixes
- #4881: synchronizing "Declare Implicit Tactic" with backtrack.
- #4882: anomaly with Declare Implicit Tactic on hole of type with evars
- Fix use of "Declare Implicit Tactic" in refine.
- triggered by |CoqIDE|
+ triggered by CoqIDE
- #4069, #4718: congruence fails when universes are involved.
Universes
@@ -5257,7 +5377,7 @@ Other bugfixes
- #5097: status of evars refined by "clear" in ltac: closed wrt evars.
- #5150: Missing dependency of the test-suite subsystems in prerequisite.
- Fix a bug in error printing of unif constraints
-- #3941: Do not stop propagation of signals when |Coq| is busy.
+- #3941: Do not stop propagation of signals when Coq is busy.
- #4822: Incorrect assertion in cbn.
- #3479 parsing of "{" and "}" when a keyword starts with "{" or "}".
- #5127: Memory corruption with the VM.
@@ -5271,9 +5391,9 @@ Version 8.4
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.4 contains the result of three long-term projects: a new
+Coq version 8.4 contains the result of three long-term projects: a new
modular library of arithmetic by Pierre Letouzey, a new proof engine by
-Arnaud Spiwack and a new communication protocol for |CoqIDE| by Vincent
+Arnaud Spiwack and a new communication protocol for CoqIDE by Vincent
Gross.
The new modular library of arithmetic extends, generalizes and unifies
@@ -5295,16 +5415,16 @@ goals simultaneously, for reordering goals, all features which are
planned for the next release. The new proof engine forced Pierre Letouzey
to reimplement info and Show Script differently.
-Before version 8.4, |CoqIDE| was linked to |Coq| with the graphical
-interface living in a separate thread. From version 8.4, |CoqIDE| is a
-separate process communicating with |Coq| through a textual channel. This
-allows for a more robust interfacing, the ability to interrupt |Coq|
+Before version 8.4, CoqIDE was linked to Coq with the graphical
+interface living in a separate thread. From version 8.4, CoqIDE is a
+separate process communicating with Coq through a textual channel. This
+allows for a more robust interfacing, the ability to interrupt Coq
without interrupting the interface, and the ability to manage several
sessions in parallel. Relying on the infrastructure work made by Vincent
Gross, Pierre Letouzey, Pierre Boutillier and Pierre-Marie Pédrot
-contributed many various refinements of |CoqIDE|.
+contributed many various refinements of CoqIDE.
-|Coq| 8.4 also comes with a bunch of various smaller-scale changes
+Coq 8.4 also comes with a bunch of various smaller-scale changes
and improvements regarding the different components of the system.
The underlying logic has been extended with :math:`\eta`-conversion
@@ -5313,7 +5433,7 @@ addition of :math:`\eta`-conversion is justified by the confidence that
the formulation of the Calculus of Inductive Constructions based on
typed equality (such as the one considered in Lee and Werner to build a
set-theoretic model of CIC :cite:`LeeWerner11`) is
-applicable to the concrete implementation of |Coq|.
+applicable to the concrete implementation of Coq.
The underlying logic benefited also from a refinement of the guard
condition for fixpoints by Pierre Boutillier, the point being that it is
@@ -5382,19 +5502,19 @@ Julien Forest maintained the Function command.
Matthieu Sozeau maintained the setoid rewriting mechanism.
-|Coq| related tools have been upgraded too. In particular, coq\_makefile
+Coq related tools have been upgraded too. In particular, coq\_makefile
has been largely revised by Pierre Boutillier. Also, patches from Adam
Chlipala for coqdoc have been integrated by Pierre Boutillier.
Bruno Barras and Pierre Letouzey maintained the `coqchk` checker.
Pierre Courtieu and Arnaud Spiwack contributed new features for using
-|Coq| through Proof General.
+Coq through Proof General.
The Dp plugin has been removed. Use the plugin provided with Why 3
instead (http://why3.lri.fr/).
-Under the hood, the |Coq| architecture benefited from improvements in
+Under the hood, the Coq architecture benefited from improvements in
terms of efficiency and robustness, especially regarding universes
management and existential variables management, thanks to Pierre
Letouzey and Yann Régis-Gianas with contributions from Stéphane Glondu
@@ -5641,7 +5761,7 @@ Libraries
* "<?" "<=?" "=?" for boolean tests such as Z.ltb Z.leb Z.eqb.
* "÷" for the alternative integer division Z.quot implementing the Truncate
- convention (former ZOdiv), while the notation for the |Coq| usual division
+ convention (former ZOdiv), while the notation for the Coq usual division
Z.div implementing the Flooring convention remains "/". Their corresponding
modulo functions are Z.rem (no notations) for Z.quot and Z.modulo (infix
"mod" notation) for Z.div.
@@ -5701,31 +5821,31 @@ Extraction
universe polymorphism it cannot handle yet (the pair (I,I) being Prop).
- Support of anonymous fields in record (#2555).
-|CoqIDE|
+CoqIDE
-- |CoqIDE| now runs coqtop as separated process, making it more robust:
+- CoqIDE now runs coqtop as separated process, making it more robust:
coqtop subprocess can be interrupted, or even killed and relaunched
(cf button "Restart Coq", ex-"Go to Start"). For allowing such
interrupts, the Windows version of coqide now requires Windows >= XP
SP1.
-- The communication between |CoqIDE| and coqtop is now done via a dialect
+- The communication between CoqIDE and coqtop is now done via a dialect
of XML (DOC TODO).
-- The backtrack engine of |CoqIDE| has been reworked, it now uses the
+- The backtrack engine of CoqIDE has been reworked, it now uses the
"Backtrack" command similarly to Proof General.
-- The |CoqIDE| parsing of sentences has be reworked and now supports
+- The CoqIDE parsing of sentences has be reworked and now supports
tactic delimitation via { }.
-- |CoqIDE| now accepts the Abort command (wish #2357).
-- |CoqIDE| can read coq_makefile files as "project file" and use it to
+- CoqIDE now accepts the Abort command (wish #2357).
+- CoqIDE can read coq_makefile files as "project file" and use it to
set automatically options to send to coqtop.
- Preference files have moved to $XDG_CONFIG_HOME/coq and accelerators
are not stored as a list anymore.
Tools
-- |Coq| now searches directories specified in COQPATH, $XDG_DATA_HOME/coq,
+- Coq now searches directories specified in COQPATH, $XDG_DATA_HOME/coq,
$XDG_DATA_DIRS/coq, and user-contribs before the standard library.
-- |Coq| rc file has moved to $XDG_CONFIG_HOME/coq.
+- Coq rc file has moved to $XDG_CONFIG_HOME/coq.
- Major changes to coq_makefile:
@@ -5783,9 +5903,9 @@ Module System
namespace from ordinary definitions: "Definition E:=0. Module E. End E."
is now accepted.
-|CoqIDE|
+CoqIDE
-- |CoqIDE| now supports the "Restart" command, and "Undo" (with a warning).
+- CoqIDE now supports the "Restart" command, and "Undo" (with a warning).
Better support for "Abort".
Details of changes in 8.4
@@ -5802,9 +5922,9 @@ Vernacular commands
Notations
- Most compatibility notations of the standard library are now tagged as
- (compat xyz), where xyz is a former |Coq| version, for instance "8.3".
+ (compat xyz), where xyz is a former Coq version, for instance "8.3".
These notations behave as (only parsing) notations, except that they may
- triggers warnings (or errors) when used while |Coq| is not in a corresponding
+ triggers warnings (or errors) when used while Coq is not in a corresponding
-compat mode.
- To activate these compatibility warnings, use "Set Verbose Compat Notations"
or the command-line flag -verbose-compat-notations.
@@ -5834,7 +5954,7 @@ Version 8.3
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.3 is before all a transition version with refinements or
+Coq version 8.3 is before all a transition version with refinements or
extensions of the existing features and libraries and a new tactic nsatz
based on Hilbert’s Nullstellensatz for deciding systems of equations
over rings.
@@ -5873,7 +5993,7 @@ been done by Matthieu Sozeau, Hugo Herbelin and Pierre Letouzey.
Matthieu Sozeau extended and refined the typeclasses and Program
features (the Russell language). Pierre Letouzey maintained and improved
the extraction mechanism. Bruno Barras and Élie Soubiran maintained the
-|Coq| checker, Julien Forest maintained the Function mechanism for
+Coq checker, Julien Forest maintained the Function mechanism for
reasoning over recursively defined functions. Matthieu Sozeau, Hugo
Herbelin and Jean-Marc Notin maintained coqdoc. Frédéric Besson
maintained the Micromega platform for deciding systems of inequalities.
@@ -5887,8 +6007,8 @@ more robust basis.
Though invisible from outside, Arnaud Spiwack improved the general
process of management of existential variables. Pierre Letouzey and
-Stéphane Glondu improved the compilation scheme of the |Coq| archive.
-Vincent Gross provided support to |CoqIDE|. Jean-Marc Notin provided
+Stéphane Glondu improved the compilation scheme of the Coq archive.
+Vincent Gross provided support to CoqIDE. Jean-Marc Notin provided
support for benchmarking and archiving.
Many users helped by reporting problems, providing patches, suggesting
@@ -6037,12 +6157,12 @@ Module system
"Inline" annotation in the type of its argument(s) (for examples of
use of the new features, see libraries Structures and Numbers).
- Coercions are now active only when modules are imported (use "Set Automatic
- Coercions Import" to get the behavior of the previous versions of |Coq|).
+ Coercions Import" to get the behavior of the previous versions of Coq).
Extraction
- When using (Recursive) Extraction Library, the filenames are directly the
- |Coq| ones with new appropriate extensions : we do not force anymore
+ Coq ones with new appropriate extensions : we do not force anymore
uncapital first letters for Ocaml and capital ones for Haskell.
- The extraction now tries harder to avoid code transformations that can be
dangerous for the complexity. In particular many eta-expansions at the top
@@ -6125,7 +6245,7 @@ Vernacular commands
Library
-- Use "standard" |Coq| names for the properties of eq and identity
+- Use "standard" Coq names for the properties of eq and identity
(e.g. refl_equal is now eq_refl). Support for compatibility is provided.
- The function Compare_dec.nat_compare is now defined directly,
@@ -6176,7 +6296,7 @@ Library
- MSets library: an important evolution of the FSets library.
"MSets" stands for Modular (Finite) Sets, by contrast with a forthcoming
library of Class (Finite) Sets contributed by S. Lescuyer which will be
- integrated with the next release of |Coq|. The main features of MSets are:
+ integrated with the next release of Coq. The main features of MSets are:
+ The use of Equivalence, Proper and other Type Classes features
easing the handling of setoid equalities.
@@ -6191,7 +6311,7 @@ Library
Note: No Maps yet in MSets. The FSets library is still provided
for compatibility, but will probably be considered as deprecated in the
- next release of |Coq|.
+ next release of Coq.
- Numbers library:
@@ -6207,12 +6327,12 @@ Library
Tools
-- Option -R now supports binding |Coq| root read-only.
+- Option -R now supports binding Coq root read-only.
- New coqtop/coqc option -beautify to reformat .v files (usable
e.g. to globally update notations).
- New tool beautify-archive to beautify a full archive of developments.
- New coqtop/coqc option -compat X.Y to simulate the general behavior
- of previous versions of |Coq| (provides e.g. support for 8.2 compatibility).
+ of previous versions of Coq (provides e.g. support for 8.2 compatibility).
Coqdoc
@@ -6228,7 +6348,7 @@ Coqdoc
- New option "--parse-comments" to allow parsing of regular ``(* *)``
comments.
- New option "--plain-comments" to disable interpretation inside comments.
-- New option "--interpolate" to try and typeset identifiers in |Coq| escapings
+- New option "--interpolate" to try and typeset identifiers in Coq escapings
using the available globalization information.
- New option "--external url root" to refer to external libraries.
- Links to section variables and notations now supported.
@@ -6242,7 +6362,7 @@ Internal infrastructure
- An experimental build mechanism via ocamlbuild is provided.
From the top of the archive, run ./configure as usual, and
then ./build. Feedback about this build mechanism is most welcome.
- Compiling |Coq| on platforms such as Windows might be simpler
+ Compiling Coq on platforms such as Windows might be simpler
this way, but this remains to be tested.
- The Makefile system has been simplified and factorized with
the ocamlbuild system. In particular "make" takes advantage
@@ -6255,19 +6375,19 @@ Version 8.2
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.2 adds new features, new libraries and improves on many
+Coq version 8.2 adds new features, new libraries and improves on many
various aspects.
-Regarding the language of |Coq|, the main novelty is the introduction by
+Regarding the language of Coq, the main novelty is the introduction by
Matthieu Sozeau of a package of commands providing Haskell-style typeclasses.
Typeclasses, which come with a few convenient features such as
type-based resolution of implicit arguments, play a new landmark role
-in the architecture of |Coq| with respect to automation. For
+in the architecture of Coq with respect to automation. For
instance, thanks to typeclass support, Matthieu Sozeau could
implement a new resolution-based version of the tactics dedicated to
rewriting on arbitrary transitive relations.
-Another major improvement of |Coq| 8.2 is the evolution of the arithmetic
+Another major improvement of Coq 8.2 is the evolution of the arithmetic
libraries and of the tools associated to them. Benjamin Grégoire and
Laurent Théry contributed a modular library for building arbitrarily
large integers from bounded integers while Evgeny Makarov contributed a
@@ -6291,7 +6411,7 @@ Arnaud Spiwack developed a library of 31-bits machine integers and,
relying on Benjamin Grégoire and Laurent Théry’s library, delivered a
library of unbounded integers in base :math:`2^{31}`. As importantly, he
developed a notion of “retro-knowledge” so as to safely extend the
-kernel-located bytecode-based efficient evaluation algorithm of |Coq|
+kernel-located bytecode-based efficient evaluation algorithm of Coq
version 8.1 to use 31-bits machine arithmetic for efficiently computing
with the library of integers he developed.
@@ -6323,16 +6443,16 @@ the Scheme command and of injection.
Bruno Barras implemented the ``coqchk`` tool: this is a stand-alone
type checker that can be used to certify .vo files. Especially, as this
verifier runs in a separate process, it is granted not to be “hijacked”
-by virtually malicious extensions added to |Coq|.
+by virtually malicious extensions added to Coq.
Yves Bertot, Jean-Christophe Filliâtre, Pierre Courtieu and Julien
Forest acted as maintainers of features they implemented in previous
-versions of |Coq|.
+versions of Coq.
-Julien Narboux contributed to |CoqIDE|. Nicolas Tabareau made the
+Julien Narboux contributed to CoqIDE. Nicolas Tabareau made the
adaptation of the interface of the old “setoid rewrite” tactic to the
-new version. Lionel Mamane worked on the interaction between |Coq| and its
-external interfaces. With Samuel Mimram, he also helped making |Coq|
+new version. Lionel Mamane worked on the interaction between Coq and its
+external interfaces. With Samuel Mimram, he also helped making Coq
compatible with recent software tools. Russell O’Connor, Cezary
Kaliszyk, Milad Niqui contributed to improve the libraries of integers,
rational, and real numbers. We also thank many users and partners for
@@ -6410,7 +6530,7 @@ Vernacular commands
qualified names (this holds also for coqtop/coqc option -R).
- SearchAbout supports negated search criteria, reference to logical objects
by their notation, and more generally search of subterms.
-- "Declare ML Module" now allows to import .cmxs files when |Coq| is
+- "Declare ML Module" now allows to import .cmxs files when Coq is
compiled in native code with a version of OCaml that supports native
Dynlink (>= 3.11).
- Specific sort constraints on Record now taken into account.
@@ -6451,7 +6571,7 @@ Libraries
version should be fairly good, but some adaptations may be required.
* Interfaces of unordered ("weak") and ordered sets have been factorized
- thanks to new features of |Coq| modules (in particular Include), see
+ thanks to new features of Coq modules (in particular Include), see
FSetInterface. Same for maps. Hints in these interfaces have been
reworked (they are now placed in a "set" database).
* To allow full subtyping between weak and ordered sets, a field
@@ -6482,7 +6602,7 @@ Libraries
initial Ocaml code and written via the Function framework.
- Library IntMap, subsumed by FSets/FMaps, has been removed from
- |Coq| Standard Library and moved into a user contribution Cachan/IntMap
+ Coq Standard Library and moved into a user contribution Cachan/IntMap
- Better computational behavior of some constants (eq_nat_dec and
le_lt_dec more efficient, Z_lt_le_dec and Positive_as_OT.compare
@@ -6687,7 +6807,7 @@ Tactics
- New tactic "specialize H with a" or "specialize (H a)" allows to transform
in-place a universally-quantified hypothesis (H : forall x, T x) into its
instantiated form (H : T a). Nota: "specialize" was in fact there in earlier
- versions of |Coq|, but was undocumented, and had a slightly different behavior.
+ versions of Coq, but was undocumented, and had a slightly different behavior.
- New tactic "contradict H" can be used to solve any kind of goal as long as
the user can provide afterwards a proof of the negation of the hypothesis H.
@@ -6731,7 +6851,7 @@ Program
- Program Lemma, Axiom etc... now permit to have obligations in the statement
iff they can be automatically solved by the default tactic.
- Renamed "Obligations Tactic" command to "Obligation Tactic".
-- New command "Preterm [ of id ]" to see the actual term fed to |Coq| for
+- New command "Preterm [ of id ]" to see the actual term fed to Coq for
debugging purposes.
- New option "Transparent Obligations" to control the declaration of
obligations as transparent or opaque. All obligations are now transparent
@@ -6823,7 +6943,7 @@ Extraction
not happen anymore.
- The command Extract Inductive has now a syntax for infix notations. This
- allows in particular to map |Coq| lists and pairs onto |OCaml| ones:
+ allows in particular to map Coq lists and pairs onto OCaml ones:
+ Extract Inductive list => list [ "[]" "(::)" ].
+ Extract Inductive prod => "(*)" [ "(,)" ].
@@ -6837,16 +6957,16 @@ Extraction
conflits with existing code, for instance when extracting module List
to Ocaml.
-|CoqIDE|
+CoqIDE
-- |CoqIDE| font defaults to monospace so as indentation to be meaningful.
-- |CoqIDE| supports nested goals and any other kind of declaration in the middle
+- CoqIDE font defaults to monospace so as indentation to be meaningful.
+- CoqIDE supports nested goals and any other kind of declaration in the middle
of a proof.
-- Undoing non-tactic commands in |CoqIDE| works faster.
-- New |CoqIDE| menu for activating display of various implicit informations.
+- Undoing non-tactic commands in CoqIDE works faster.
+- New CoqIDE menu for activating display of various implicit informations.
- Added the possibility to choose the location of tabs in coqide:
(in Edit->Preferences->Misc)
-- New Open and Save As dialogs in |CoqIDE| which filter ``*.v`` files.
+- New Open and Save As dialogs in CoqIDE which filter ``*.v`` files.
Tools
@@ -6855,22 +6975,22 @@ Tools
- New coqtop/coqc option -exclude-dir to exclude subdirs for option -R.
- The binary "parser" has been renamed to "coq-parser".
- Improved coqdoc and dump of globalization information to give more
- meta-information on identifiers. All categories of |Coq| definitions are
+ meta-information on identifiers. All categories of Coq definitions are
supported, which makes typesetting trivial in the generated documentation.
Support for hyperlinking and indexing developments in the tex output
has been implemented as well.
Miscellaneous
-- |Coq| installation provides enough files so that Ocaml's extensions need not
- the |Coq| sources to be compiled (this assumes O'Caml 3.10 and Camlp5).
+- Coq installation provides enough files so that Ocaml's extensions need not
+ the Coq sources to be compiled (this assumes O'Caml 3.10 and Camlp5).
- New commands "Set Whelp Server" and "Set Whelp Getter" to customize the
Whelp search tool.
- Syntax of "Test Printing Let ref" and "Test Printing If ref" changed into
"Test Printing Let for ref" and "Test Printing If for ref".
- An overhauled build system (new Makefiles); see dev/doc/build-system.txt.
- Add -browser option to configure script.
-- Build a shared library for the C part of |Coq|, and use it by default on
+- Build a shared library for the C part of Coq, and use it by default on
non-(Windows or MacOS) systems. Bytecode executables are now pure. The
behaviour is configurable with -coqrunbyteflags, -coqtoolsbyteflags and
-custom configure options.
@@ -6883,10 +7003,10 @@ Version 8.1
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8.1 adds various new functionalities.
+Coq version 8.1 adds various new functionalities.
Benjamin Grégoire implemented an alternative algorithm to check the
-convertibility of terms in the |Coq| type checker. This alternative
+convertibility of terms in the Coq type checker. This alternative
algorithm works by compilation to an efficient bytecode that is
interpreted in an abstract machine similar to Xavier Leroy’s ZINC
machine. Convertibility is performed by comparing the normal forms. This
@@ -6916,7 +7036,7 @@ Claudio Sacerdoti Coen added new tactic features.
Hugo Herbelin implemented matching on disjunctive patterns.
-New mechanisms made easier the communication between |Coq| and external
+New mechanisms made easier the communication between Coq and external
provers. Nicolas Ayache and Jean-Christophe Filliâtre implemented
connections with the provers cvcl, Simplify and zenon. Hugo Herbelin
implemented an experimental protocol for calling external tools from the
@@ -6930,7 +7050,7 @@ unresolved implicit has been implemented by Hugo Herbelin.
Laurent Théry’s contribution on strings and Pierre Letouzey and
Jean-Christophe Filliâtre’s contribution on finite maps have been
-integrated to the |Coq| standard library. Pierre Letouzey developed a
+integrated to the Coq standard library. Pierre Letouzey developed a
library about finite sets “à la Objective Caml”. With Jean-Marc Notin,
he extended the library on lists. Pierre Letouzey’s contribution on
rational numbers has been integrated and extended.
@@ -6991,7 +7111,7 @@ Vernacular commands
Ltac and tactic syntactic extensions
-- New primitive "external" for communication with tool external to |Coq|
+- New primitive "external" for communication with tool external to Coq
- New semantics for "match t with": if a clause returns a
tactic, it is now applied to the current goal. If it fails, the next
clause or next matching subterm is tried (i.e. it behaves as "match
@@ -7016,7 +7136,7 @@ Tactics
- New conversion tactic "vm_compute": evaluates the goal (or an hypothesis)
with a call-by-value strategy, using the compiled version of terms.
-- When rewriting H where H is not directly a |Coq| equality, search first H for
+- When rewriting H where H is not directly a Coq equality, search first H for
a registered setoid equality before starting to reduce in H. This is unlikely
to break any script. Should this happen nonetheless, one can insert manually
some "unfold ... in H" before rewriting.
@@ -7061,7 +7181,7 @@ Tactics
- New tactic "pose proof" that generalizes "assert (id:=p)" with intro patterns.
-- New introduction pattern "?" for letting |Coq| choose a name.
+- New introduction pattern "?" for letting Coq choose a name.
- Introduction patterns now support side hypotheses (e.g. intros [|] on
"(nat -> nat) -> nat" works).
@@ -7147,7 +7267,7 @@ Libraries
Zlt_square_simpl removed; fixed names mentioning letter O instead of
digit 0; weaken premises in Z_lt_induction).
- Restructuration of Eqdep_dec.v and Eqdep.v: more lemmas in Type.
-- Znumtheory now contains a gcd function that can compute within |Coq|.
+- Znumtheory now contains a gcd function that can compute within Coq.
- More lemmas stated on Type in Wf.v, removal of redundant Acc_iter and
Acc_iter2.
- Change of the internal names of lemmas in OmegaLemmas.
@@ -7180,7 +7300,7 @@ Tools
- Tool coq_makefile now removes custom targets that are file names in
"make clean"
- New environment variable COQREMOTEBROWSER to set the command invoked
- to start the remote browser both in |Coq| and |CoqIDE|. Standard syntax:
+ to start the remote browser both in Coq and CoqIDE. Standard syntax:
"%s" is the placeholder for the URL.
Details of changes in 8.1gamma
@@ -7256,7 +7376,7 @@ Version 8.0
Summary of changes
~~~~~~~~~~~~~~~~~~
-|Coq| version 8 is a major revision of the |Coq| proof assistant. First, the
+Coq version 8 is a major revision of the Coq proof assistant. First, the
underlying logic is slightly different. The so-called *impredicativity*
of the sort Set has been dropped. The main reason is that it is
inconsistent with the principle of description which is quite a useful
@@ -7285,7 +7405,7 @@ main motivations were
Together with the revision of the concrete syntax, a new mechanism of
*notation scopes* permits to reuse the same symbols (typically +,
-, \*, /, <, <=) in various mathematical theories without any
-ambiguities for |Coq|, leading to a largely improved readability of |Coq|
+ambiguities for Coq, leading to a largely improved readability of Coq
scripts. New commands to easily add new symbols are also provided.
Coming with the new syntax of terms, a slight reform of the tactic
@@ -7294,30 +7414,30 @@ purpose here is a better uniformity making the tactics and commands
easier to use and to remember.
Thirdly, a restructuring and uniformization of the standard library of
-|Coq| has been performed. There is now just one Leibniz equality usable
-for all the different kinds of |Coq| objects. Also, the set of real
+Coq has been performed. There is now just one Leibniz equality usable
+for all the different kinds of Coq objects. Also, the set of real
numbers now lies at the same level as the sets of natural and integer
numbers. Finally, the names of the standard properties of numbers now
follow a standard pattern and the symbolic notations for the standard
definitions as well.
-The fourth point is the release of |CoqIDE|, a new graphical gtk2-based
-interface fully integrated with |Coq|. Close in style to the Proof General
-Emacs interface, it is faster and its integration with |Coq| makes
+The fourth point is the release of CoqIDE, a new graphical gtk2-based
+interface fully integrated with Coq. Close in style to the Proof General
+Emacs interface, it is faster and its integration with Coq makes
interactive developments more friendly. All mathematical Unicode symbols
-are usable within |CoqIDE|.
+are usable within CoqIDE.
-Finally, the module system of |Coq| completes the picture of |Coq| version
+Finally, the module system of Coq completes the picture of Coq version
8.0. Though released with an experimental status in the previous version
7.4, it should be considered as a salient feature of the new version.
-Besides, |Coq| comes with its load of novelties and improvements: new or
+Besides, Coq comes with its load of novelties and improvements: new or
improved tactics (including a new tactic for solving first-order
statements), new management commands, extended libraries.
Bruno Barras and Hugo Herbelin have been the main contributors of the
reflection and the implementation of the new syntax. The smart automatic
-translator from old to new syntax released with |Coq| is also their work
+translator from old to new syntax released with Coq is also their work
with contributions by Olivier Desmettre.
Hugo Herbelin is the main designer and implementer of the notion of
@@ -7330,21 +7450,21 @@ Pierre Corbineau is the main designer and implementer of the new tactic
for solving first-order statements in presence of inductive types. He is
also the maintainer of the non-domain specific automation tactics.
-Benjamin Monate is the developer of the |CoqIDE| graphical interface with
+Benjamin Monate is the developer of the CoqIDE graphical interface with
contributions by Jean-Christophe Filliâtre, Pierre Letouzey, Claude
Marché and Bruno Barras.
-Claude Marché coordinated the edition of the Reference Manual for |Coq|
+Claude Marché coordinated the edition of the Reference Manual for Coq
V8.0.
Pierre Letouzey and Jacek Chrząszcz respectively maintained the
-extraction tool and module system of |Coq|.
+extraction tool and module system of Coq.
Jean-Christophe Filliâtre, Pierre Letouzey, Hugo Herbelin and other
contributors from Sophia-Antipolis and Nijmegen participated in
extending the library.
-Julien Narboux built a NSIS-based automatic |Coq| installation tool for
+Julien Narboux built a NSIS-based automatic Coq installation tool for
the Windows platform.
Hugo Herbelin and Christine Paulin coordinated the development which was
@@ -7511,19 +7631,19 @@ Miscellaneous
Incompatibilities
-- Persistence of true_sub (4 incompatibilities in |Coq| user contributions)
+- Persistence of true_sub (4 incompatibilities in Coq user contributions)
- Variable names of some constants changed for a better uniformity (2 changes
- in |Coq| user contributions)
+ in Coq user contributions)
- Naming of quantified names in goal now avoid global names (2 occurrences)
- NewInduction naming for inductive types with functional arguments
- (no incompatibility in |Coq| user contributions)
+ (no incompatibility in Coq user contributions)
- Contradiction now solve more goals (source of 2 incompatibilities)
- Merge of eq and eqT may exceptionally result in subgoals now
solved automatically
- Redundant pairs of ZArith lemmas may have different names: it may
cause "Apply/Rewrite with" to fail if using the first name of a pair
of redundant lemmas (this is solved by renaming the variables bound by
- "with"; 3 incompatibilities in |Coq| user contribs)
+ "with"; 3 incompatibilities in Coq user contribs)
- ML programs referring to constants from fast_integer.v must use
"Coqlib.gen_constant_modules Coqlib.zarith_base_modules" instead
@@ -7559,7 +7679,7 @@ Revision of the standard library
"Zmult_le_compat_r", "SUPERIEUR" -> "Gt", "ZERO" -> "Z0")
- Order and names of arguments of basic lemmas on nat, Z, positive and R
have been made uniform.
-- Notions of |Coq| initial state are declared with (strict) implicit arguments
+- Notions of Coq initial state are declared with (strict) implicit arguments
- eq merged with eqT: old eq disappear, new eq (written =) is old eqT
and new eqT is syntactic sugar for new eq (notation == is an alias
for = and is written as it, exceptional source of incompatibilities)
@@ -7590,7 +7710,7 @@ Known problems of the automatic translation
- iso-latin-1 characters are no longer supported: move your files to
7-bits ASCII or unicode before translation (switch to unicode is
automatically done if a file is loaded and saved again by coqide)
-- Renaming in ZArith: incompatibilities in |Coq| user contribs due to
+- Renaming in ZArith: incompatibilities in Coq user contribs due to
merging names INZ, from Reals, and inject_nat.
- Renaming and new lemmas in ZArith: may clash with names used by users
- Restructuration of ZArith: replace requirement of specific modules
@@ -7640,7 +7760,7 @@ Tactics and the tactic Language
Executables and tools
- Added option -top to change the name of the toplevel module "Top"
-- Coqdoc updated to new syntax and now part of |Coq| sources
+- Coqdoc updated to new syntax and now part of Coq sources
- XML exportation tool now exports the structure of vernacular files
(cf chapter 13 in the reference manual)
diff --git a/doc/sphinx/history.rst b/doc/sphinx/history.rst
index bab9bfcadb..c5ef92a1bf 100644
--- a/doc/sphinx/history.rst
+++ b/doc/sphinx/history.rst
@@ -1,23 +1,23 @@
.. _history:
----------------------
-Early history of |Coq|
+Early history of Coq
----------------------
Historical roots
----------------
-|Coq| is a proof assistant for higher-order logic, allowing the
+Coq is a proof assistant for higher-order logic, allowing the
development of computer programs consistent with their formal
specification. It is the result of about ten years [#years]_ of research
-of the |Coq| project. We shall briefly survey here three main aspects: the
+of the Coq project. We shall briefly survey here three main aspects: the
*logical language* in which we write our axiomatizations and
specifications, the *proof assistant* which allows the development of
verified mathematical proofs, and the *program extractor* which
synthesizes computer programs obeying their formal specifications,
written as logical assertions in the language.
-The logical language used by |Coq| is a variety of type theory, called the
+The logical language used by Coq is a variety of type theory, called the
*Calculus of Inductive Constructions*. Without going back to Leibniz and
Boole, we can date the creation of what is now called mathematical logic
to the work of Frege and Peano at the turn of the century. The discovery
@@ -108,7 +108,7 @@ modules, automatically generated from a consistency proof of their
formal specifications. We are however still far from being able to use
this methodology in a smooth interaction with the standard tools from
software engineering, i.e. compilers, linkers, run-time systems taking
-advantage of special hardware, debuggers, and the like. We hope that |Coq|
+advantage of special hardware, debuggers, and the like. We hope that Coq
can be of use to researchers interested in experimenting with this new
methodology.
@@ -153,8 +153,8 @@ by A. Felty. It allowed operation of the theorem-prover through the
manipulation of windows, menus, mouse-sensitive buttons, and other
widgets. This system (Version 5.6) was released in 1991.
-|Coq| was ported to the new implementation Caml-light of X. Leroy and D.
-Doligez by D. de Rauglaudre (Version 5.7) in 1992. A new version of |Coq|
+Coq was ported to the new implementation Caml-light of X. Leroy and D.
+Doligez by D. de Rauglaudre (Version 5.7) in 1992. A new version of Coq
was then coordinated by C. Murthy, with new tools designed by C. Parent
to prove properties of ML programs (this methodology is dual to program
extraction) and a new user-interaction loop. This system (Version 5.8)
@@ -163,9 +163,9 @@ by Y. Bertot from the Croap project from INRIA-Sophia-Antipolis.
In parallel, G. Dowek and H. Herbelin developed a new proof engine,
allowing the general manipulation of existential variables consistently
-with dependent types in an experimental version of |Coq| (V5.9).
+with dependent types in an experimental version of Coq (V5.9).
-The version V5.10 of |Coq| is based on a generic system for manipulating
+The version V5.10 of Coq is based on a generic system for manipulating
terms with binding operators due to Chet Murthy. A new proof engine
allows the parallel development of partial proofs for independent
subgoals. The structure of these proof trees is a mixed representation
@@ -477,7 +477,7 @@ C. Paulin-Mohring. *Inductively defined types* :cite:`CP90`.
This led to the Calculus of Inductive Constructions, logical formalism
implemented in Versions 5 upward of the system, and documented in:
-C. Paulin-Mohring. *Inductive Definitions in the System |Coq| - Rules
+C. Paulin-Mohring. *Inductive Definitions in the System Coq - Rules
and Properties* :cite:`P93`.
The last version of CONSTR is Version 4.11, which was last distributed
@@ -489,7 +489,7 @@ Version 5
~~~~~~~~~
At the end of 1989, Version 5.1 was started, and renamed as the system
-|Coq| for the Calculus of Inductive Constructions. It was then ported to
+Coq for the Calculus of Inductive Constructions. It was then ported to
the new stand-alone implementation of ML called Caml-light.
In 1990 many changes occurred. Thierry Coquand left for Chalmers
@@ -497,7 +497,7 @@ University in Göteborg. Christine Paulin-Mohring took a CNRS
researcher position at the LIP laboratory of École Normale Supérieure
de Lyon. Project Formel was terminated, and gave rise to two teams:
Cristal at INRIA-Roquencourt, that continued developments in
-functional programming with Caml-light then OCaml, and |Coq|, continuing
+functional programming with Caml-light then OCaml, and Coq, continuing
the type theory research, with a joint team headed by Gérard Huet at
INRIA-Rocquencourt and Christine Paulin-Mohring at the LIP laboratory
of CNRS-ENS Lyon.
@@ -519,14 +519,14 @@ Versions 6
Version 6.1
~~~~~~~~~~~
-The present version 6.1 of |Coq| is based on the V5.10 architecture. It
+The present version 6.1 of Coq is based on the V5.10 architecture. It
was ported to the new language Objective Caml by Bruno Barras. The
underlying framework has slightly changed and allows more conversions
between sorts.
The new version provides powerful tools for easier developments.
-Cristina Cornes designed an extension of the |Coq| syntax to allow
+Cristina Cornes designed an extension of the Coq syntax to allow
definition of terms using a powerful pattern matching analysis in the
style of ML programs.
@@ -539,13 +539,13 @@ written.
Yann Coscoy designed a command which explains a proof term using natural
language. Pierre Crégut built a new tactic which solves problems in
quantifier-free Presburger Arithmetic. Both functionalities have been
-integrated to the |Coq| system by Hugo Herbelin.
+integrated to the Coq system by Hugo Herbelin.
Samuel Boutin designed a tactic for simplification of commutative rings
using a canonical set of rewriting rules and equality modulo
associativity and commutativity.
-Finally the organisation of the |Coq| distribution has been supervised by
+Finally the organisation of the Coq distribution has been supervised by
Jean-Christophe Filliâtre with the help of Judicaël Courant and Bruno
Barras.
@@ -556,21 +556,21 @@ Barras.
Version 6.2
~~~~~~~~~~~
-In version 6.2 of |Coq|, the parsing is done using camlp4, a preprocessor
+In version 6.2 of Coq, the parsing is done using camlp4, a preprocessor
and pretty-printer for CAML designed by Daniel de Rauglaudre at INRIA.
-Daniel de Rauglaudre made the first adaptation of |Coq| for camlp4, this
-work was continued by Bruno Barras who also changed the structure of |Coq|
+Daniel de Rauglaudre made the first adaptation of Coq for camlp4, this
+work was continued by Bruno Barras who also changed the structure of Coq
abstract syntax trees and the primitives to manipulate them. The result
of these changes is a faster parsing procedure with greatly improved
syntax-error messages. The user-interface to introduce grammar or
pretty-printing rules has also changed.
Eduardo Giménez redesigned the internal tactic libraries, giving uniform
-names to Caml functions corresponding to |Coq| tactic names.
+names to Caml functions corresponding to Coq tactic names.
Bruno Barras wrote new, more efficient reduction functions.
-Hugo Herbelin introduced more uniform notations in the |Coq| specification
+Hugo Herbelin introduced more uniform notations in the Coq specification
language: the definitions by fixpoints and pattern matching have a more
readable syntax. Patrick Loiseleur introduced user-friendly notations
for arithmetic expressions.
@@ -586,10 +586,10 @@ a proof term with holes as a proof scheme.
David Delahaye designed the tool to search an object in the library
given its type (up to isomorphism).
-Henri Laulhère produced the |Coq| distribution for the Windows
+Henri Laulhère produced the Coq distribution for the Windows
environment.
-Finally, Hugo Herbelin was the main coordinator of the |Coq| documentation
+Finally, Hugo Herbelin was the main coordinator of the Coq documentation
with principal contributions by Bruno Barras, David Delahaye,
Jean-Christophe Filliâtre, Eduardo Giménez, Hugo Herbelin and Patrick
Loiseleur.
@@ -639,7 +639,7 @@ Summary of changes
The version V7 is a new implementation started in September 1999 by
Jean-Christophe Filliâtre. This is a major revision with respect to the
-internal architecture of the system. The |Coq| version 7.0 was distributed
+internal architecture of the system. The Coq version 7.0 was distributed
in March 2001, version 7.1 in September 2001, version 7.2 in January
2002, version 7.3 in May 2002 and version 7.4 in February 2003.
@@ -653,13 +653,13 @@ Hugo Herbelin introduced a new structure of terms with local
definitions. He introduced “qualified” names, wrote a new
pattern matching compilation algorithm and designed a more compact
algorithm for checking the logical consistency of universes. He
-contributed to the simplification of |Coq| internal structures and the
+contributed to the simplification of Coq internal structures and the
optimisation of the system. He added basic tactics for forward reasoning
and coercions in patterns.
David Delahaye introduced a new language for tactics. General tactics
using pattern matching on goals and context can directly be written from
-the |Coq| toplevel. He also provided primitives for the design of
+the Coq toplevel. He also provided primitives for the design of
user-defined tactics in Caml.
Micaela Mayero contributed the library on real numbers. Olivier
@@ -668,16 +668,16 @@ square, square roots, finite sums, Chasles property and basic plane
geometry.
Jean-Christophe Filliâtre and Pierre Letouzey redesigned a new
-extraction procedure from |Coq| terms to Caml or Haskell programs. This
+extraction procedure from Coq terms to Caml or Haskell programs. This
new extraction procedure, unlike the one implemented in previous version
-of |Coq| is able to handle all terms in the Calculus of Inductive
+of Coq is able to handle all terms in the Calculus of Inductive
Constructions, even involving universes and strong elimination. P.
Letouzey adapted user contributions to extract ML programs when it was
sensible. Jean-Christophe Filliâtre wrote ``coqdoc``, a documentation
-tool for |Coq| libraries usable from version 7.2.
+tool for Coq libraries usable from version 7.2.
Bruno Barras improved the efficiency of the reduction algorithm and the
-confidence level in the correctness of |Coq| critical type checking
+confidence level in the correctness of Coq critical type checking
algorithm.
Yves Bertot designed the ``SearchPattern`` and ``SearchRewrite`` tools
@@ -696,7 +696,7 @@ real numbers.
Pierre Crégut developed a new, reflection-based version of the Omega
decision procedure.
-Claudio Sacerdoti Coen designed an XML output for the |Coq| modules to be
+Claudio Sacerdoti Coen designed an XML output for the Coq modules to be
used in the Hypertextual Electronic Library of Mathematics (HELM cf
http://www.cs.unibo.it/helm).
@@ -706,13 +706,13 @@ contributed by Jean Goubault was integrated in the basic theories.
Pierre Courtieu developed a command and a tactic to reason on the
inductive structure of recursively defined functions.
-Jacek Chrząszcz designed and implemented the module system of |Coq| whose
+Jacek Chrząszcz designed and implemented the module system of Coq whose
foundations are in Judicaël Courant’s PhD thesis.
The development was coordinated by C. Paulin.
Many discussions within the Démons team and the LogiCal project
-influenced significantly the design of |Coq| especially with J. Courant,
+influenced significantly the design of Coq especially with J. Courant,
J. Duprat, J. Goubault, A. Miquel, C. Marché, B. Monate and B. Werner.
Intensive users suggested improvements of the system : Y. Bertot, L.
@@ -736,7 +736,7 @@ Notes:
Main novelties
^^^^^^^^^^^^^^
-References are to |Coq| 7.1 reference manual
+References are to Coq 7.1 reference manual
- New primitive let-in construct (see sections 1.2.8 and )
- Long names (see sections 2.6 and 2.7)
@@ -770,7 +770,7 @@ Language: long names
name, the name of the module in which they are defined (Top if in
coqtop), and possibly an arbitrary long sequence of directory (e.g.
"Coq.Lists.PolyList.flat_map" where "Coq" means that "flat_map" is part
- of |Coq| standard library, "Lists" means it is defined in the Lists
+ of Coq standard library, "Lists" means it is defined in the Lists
library and "PolyList" means it is in the file Polylist) (+)
- Constructions can be referred by their base name, or, in case of
@@ -829,7 +829,7 @@ Reduction
- Constants declared as opaque (using Qed) can no longer become
transparent (a constant intended to be alternatively opaque and
transparent must be declared as transparent (using Defined)); a risk
- exists (until next |Coq| version) that Simpl and Hnf reduces opaque
+ exists (until next Coq version) that Simpl and Hnf reduces opaque
constants (*)
@@ -1171,7 +1171,7 @@ Incompatibilities
- New naming strategy for NewInduction/NewDestruct may affect 7.1 compatibility
- Extra parentheses may exceptionally be needed in tactic definitions.
-- |Coq| extensions written in |OCaml| need to be updated (see dev/changements.txt
+- Coq extensions written in OCaml need to be updated (see dev/changements.txt
for a description of the main changes in the interface files of V7.2)
- New behaviour of Intuition/Tauto may exceptionally lead to incompatibilities
@@ -1205,7 +1205,7 @@ Tactics
product if needed (source of incompatibilities)
- "Match Context" now matching more recent hypotheses first and failing only
on user errors and Fail tactic (possible source of incompatibilities)
-- Tactic Definition's without arguments now allowed in |Coq| states
+- Tactic Definition's without arguments now allowed in Coq states
- Better simplification and discrimination made by Inversion (source
of incompatibilities)
@@ -1239,7 +1239,7 @@ User Contributions
- CongruenceClosure (congruence closure decision procedure)
[Pierre Corbineau, ENS Cachan]
- MapleMode (an interface to embed Maple simplification procedures over
- rational fractions in |Coq|)
+ rational fractions in Coq)
[David Delahaye, Micaela Mayero, Chalmers University]
- Presburger: A formalization of Presburger's algorithm
[Laurent Thery, INRIA Sophia Antipolis]
@@ -1283,7 +1283,7 @@ Bug fixes
Misc
- - Ocaml version >= 3.06 is needed to compile |Coq| from sources
+ - Ocaml version >= 3.06 is needed to compile Coq from sources
- Simplification of fresh names creation strategy for Assert, Pose and
LetTac (#1402)
@@ -1398,7 +1398,7 @@ Extraction (See details in plugins/extraction/CHANGES and README):
- An experimental Scheme extraction is provided.
- Concerning OCaml, extracted code is now ensured to always type check,
thanks to automatic inserting of Obj.magic.
-- Experimental extraction of |Coq| new modules to Ocaml modules.
+- Experimental extraction of Coq new modules to Ocaml modules.
Proof rendering in natural language
diff --git a/doc/sphinx/introduction.rst b/doc/sphinx/introduction.rst
index dc16897d42..06a677d837 100644
--- a/doc/sphinx/introduction.rst
+++ b/doc/sphinx/introduction.rst
@@ -1,8 +1,8 @@
-This is the reference manual of |Coq|. |Coq| is an interactive theorem
+This is the reference manual of Coq. Coq is an interactive theorem
prover. It lets you formalize mathematical concepts and then helps
you interactively generate machine-checked proofs of theorems.
Machine checking gives users much more confidence that the proofs are
-correct compared to human-generated and -checked proofs. |Coq| has been
+correct compared to human-generated and -checked proofs. Coq has been
used in a number of flagship verification projects, including the
`CompCert verified C compiler <http://compcert.inria.fr/>`_, and has
served to verify the proof of the `four color theorem
@@ -18,49 +18,49 @@ arithmetic). :ref:`Ltac <ltac>` and its planned replacement,
combining existing tactics with looping and conditional constructs.
These permit automation of large parts of proofs and sometimes entire
proofs. Furthermore, users can add novel tactics or functionality by
-creating |Coq| plugins using |OCaml|.
+creating Coq plugins using OCaml.
-The |Coq| kernel, a small part of |Coq|, does the final verification that
+The Coq kernel, a small part of Coq, does the final verification that
the tactic-generated proof is valid. Usually the tactic-generated
proof is indeed correct, but delegating proof verification to the
kernel means that even if a tactic is buggy, it won't be able to
introduce an incorrect proof into the system.
-Finally, |Coq| also supports extraction of verified programs to
-programming languages such as |OCaml| and Haskell. This provides a way
-of executing |Coq| code efficiently and can be used to create verified
+Finally, Coq also supports extraction of verified programs to
+programming languages such as OCaml and Haskell. This provides a way
+of executing Coq code efficiently and can be used to create verified
software libraries.
-To learn |Coq|, beginners are advised to first start with a tutorial /
+To learn Coq, beginners are advised to first start with a tutorial /
book. Several such tutorials / books are listed at
https://coq.inria.fr/documentation.
This manual is organized in three main parts, plus an appendix:
-- **The first part presents the specification language of |Coq|**, that
+- **The first part presents the specification language of Coq**, that
allows to define programs and state mathematical theorems.
- :ref:`core-language` presents the language that the kernel of |Coq|
+ :ref:`core-language` presents the language that the kernel of Coq
understands. :ref:`extensions` presents the richer language, with
notations, implicits, etc. that a user can use and which is
translated down to the language of the kernel by means of an
"elaboration process".
- **The second part presents the interactive proof mode**, the central
- feature of |Coq|. :ref:`writing-proofs` introduces this interactive
+ feature of Coq. :ref:`writing-proofs` introduces this interactive
proof mode and the available proof languages.
:ref:`automatic-tactics` presents some more advanced tactics, while
:ref:`writing-tactics` is about the languages that allow a user to
combine tactics together and develop new ones.
-- **The third part shows how to use |Coq| in practice.**
+- **The third part shows how to use Coq in practice.**
:ref:`libraries` presents some of the essential reusable blocks from
the ecosystem and some particularly important extensions such as the
program extraction mechanism. :ref:`tools` documents important
- tools that a user needs to build a |Coq| project.
+ tools that a user needs to build a Coq project.
- In the appendix, :ref:`history-and-changes` presents the history of
- |Coq| and changes in recent releases. This is an important reference
- if you upgrade the version of |Coq| that you use. The various
+ Coq and changes in recent releases. This is an important reference
+ if you upgrade the version of Coq that you use. The various
:ref:`indexes <indexes>` are very useful to **quickly browse the
manual and find what you are looking for.** They are often the main
entry point to the manual.
diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst
index f1ed64e52a..85b04f6df0 100644
--- a/doc/sphinx/language/cic.rst
+++ b/doc/sphinx/language/cic.rst
@@ -1,7 +1,7 @@
Typing rules
====================================
-The underlying formal language of |Coq| is a *Calculus of Inductive
+The underlying formal language of Coq is a *Calculus of Inductive
Constructions* (|Cic|) whose inference rules are presented in this
chapter. The history of this formalism as well as pointers to related
work are provided in a separate chapter; see *Credits*.
@@ -33,7 +33,7 @@ the following rules.
#. variables, hereafter ranged over by letters :math:`x`, :math:`y`, etc., are terms
#. constants, hereafter ranged over by letters :math:`c`, :math:`d`, etc., are terms.
#. if :math:`x` is a variable and :math:`T`, :math:`U` are terms then
- :math:`∀ x:T,~U` (:g:`forall x:T, U` in |Coq| concrete syntax) is a term.
+ :math:`∀ x:T,~U` (:g:`forall x:T, U` in Coq concrete syntax) is a term.
If :math:`x` occurs in :math:`U`, :math:`∀ x:T,~U` reads as
“for all :math:`x` of type :math:`T`, :math:`U`”.
As :math:`U` depends on :math:`x`, one says that :math:`∀ x:T,~U` is
@@ -43,11 +43,11 @@ the following rules.
written: :math:`T \rightarrow U`.
#. if :math:`x` is a variable and :math:`T`, :math:`u` are terms then
:math:`λ x:T .~u` (:g:`fun x:T => u`
- in |Coq| concrete syntax) is a term. This is a notation for the
+ in Coq concrete syntax) is a term. This is a notation for the
λ-abstraction of λ-calculus :cite:`Bar81`. The term :math:`λ x:T .~u` is a function
which maps elements of :math:`T` to the expression :math:`u`.
#. if :math:`t` and :math:`u` are terms then :math:`(t~u)` is a term
- (:g:`t u` in |Coq| concrete
+ (:g:`t u` in Coq concrete
syntax). The term :math:`(t~u)` reads as “:math:`t` applied to :math:`u`”.
#. if :math:`x` is a variable, and :math:`t`, :math:`T` and :math:`u` are
terms then :math:`\letin{x}{t:T}{u}` is
@@ -91,10 +91,10 @@ Let us assume that ``mult`` is a function of type :math:`\nat→\nat→\nat` and
predicate of type :math:`\nat→\nat→ \Prop`. The λ-abstraction can serve to build
“ordinary” functions as in :math:`λ x:\nat.~(\kw{mult}~x~x)` (i.e.
:g:`fun x:nat => mult x x`
-in |Coq| notation) but may build also predicates over the natural
+in Coq notation) but may build also predicates over the natural
numbers. For instance :math:`λ x:\nat.~(\kw{eqnat}~x~0)`
(i.e. :g:`fun x:nat => eqnat x 0`
-in |Coq| notation) will represent the predicate of one variable :math:`x` which
+in Coq notation) will represent the predicate of one variable :math:`x` which
asserts the equality of :math:`x` with :math:`0`. This predicate has type
:math:`\nat → \Prop`
and it can be applied to any expression of type :math:`\nat`, say :math:`t`, to give an
@@ -524,7 +524,7 @@ One can consequently derive the following property.
The Calculus of Inductive Constructions with impredicative Set
-----------------------------------------------------------------
-|Coq| can be used as a type checker for the Calculus of Inductive
+Coq can be used as a type checker for the Calculus of Inductive
Constructions with an impredicative sort :math:`\Set` by using the compiler
option ``-impredicative-set``. For example, using the ordinary `coqtop`
command, the following is rejected,
diff --git a/doc/sphinx/language/coq-library.rst b/doc/sphinx/language/coq-library.rst
index 485dfd964d..d061ed41f1 100644
--- a/doc/sphinx/language/coq-library.rst
+++ b/doc/sphinx/language/coq-library.rst
@@ -1,28 +1,28 @@
.. _thecoqlibrary:
-The |Coq| library
+The Coq library
=================
.. index::
single: Theories
-The |Coq| library has two parts:
+The Coq library has two parts:
* The :gdef:`prelude`: definitions and theorems for
the most commonly used elementary logical notions and
- data types. |Coq| normally loads these files automatically when it starts.
+ data types. Coq normally loads these files automatically when it starts.
* The :gdef:`standard library`: general-purpose libraries with
definitions and theorems for sets, lists, sorting,
arithmetic, etc. To use these files, users must load them explicitly
with the ``Require`` command (see :ref:`compiled-files`)
-There are also many libraries provided by |Coq| users' community.
+There are also many libraries provided by Coq users' community.
These libraries and developments are available
for download at http://coq.inria.fr (see :ref:`userscontributions`).
-This chapter briefly reviews the |Coq| libraries whose contents can
+This chapter briefly reviews the Coq libraries whose contents can
also be browsed at http://coq.inria.fr/stdlib/.
@@ -32,9 +32,9 @@ The prelude
-----------
This section lists the basic notions and results which are directly
-available in the standard |Coq| system. Most of these constructions
+available in the standard Coq system. Most of these constructions
are defined in the ``Prelude`` module in directory ``theories/Init``
-in the |Coq| root directory; this includes the modules
+in the Coq root directory; this includes the modules
``Notations``,
``Logic``,
``Datatypes``,
@@ -92,7 +92,7 @@ Notation Precedence Associativity
Logic
~~~~~
-The basic library of |Coq| comes with the definitions of standard
+The basic library of Coq comes with the definitions of standard
(intuitionistic) logical connectives (they are defined as inductive
constructions). They are equipped with an appealing syntax enriching the
subclass :token:`form` of the syntactic class :token:`term`. The constructs
@@ -767,7 +767,7 @@ the modules they provide are compiled at installation time. So they
are directly accessible with the command ``Require`` (see
Section :ref:`compiled-files`).
-The different modules of the |Coq| standard library are documented
+The different modules of the Coq standard library are documented
online at https://coq.inria.fr/stdlib.
Peano’s arithmetic (nat)
diff --git a/doc/sphinx/language/core/assumptions.rst b/doc/sphinx/language/core/assumptions.rst
index a38282d41a..e029068630 100644
--- a/doc/sphinx/language/core/assumptions.rst
+++ b/doc/sphinx/language/core/assumptions.rst
@@ -117,7 +117,7 @@ Assumptions
Assumptions extend the environment with axioms, parameters, hypotheses
or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted
-by |Coq| if and only if this :n:`@type` is a correct type in the environment
+by Coq if and only if this :n:`@type` is a correct type in the environment
preexisting the declaration and if :n:`@ident` was not previously defined in
the same module. This :n:`@type` is considered to be the type (or
specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident`
diff --git a/doc/sphinx/language/core/basic.rst b/doc/sphinx/language/core/basic.rst
index 29a2b40162..5406da38a1 100644
--- a/doc/sphinx/language/core/basic.rst
+++ b/doc/sphinx/language/core/basic.rst
@@ -10,7 +10,7 @@ manual. Then, we present the essential vocabulary necessary to read
the rest of the manual. Other terms are defined throughout the manual.
The reader may refer to the :ref:`glossary index <glossary_index>`
for a complete list of defined terms. Finally, we describe the various types of
-settings that |Coq| provides.
+settings that Coq provides.
Syntax and lexical conventions
------------------------------
@@ -21,7 +21,7 @@ Syntax conventions
~~~~~~~~~~~~~~~~~~
The syntax described in this documentation is equivalent to that
-accepted by the |Coq| parser, but the grammar has been edited
+accepted by the Coq parser, but the grammar has been edited
to improve readability and presentation.
In the grammar presented in this manual, the terminal symbols are
@@ -49,13 +49,13 @@ graphically using the following kinds of blocks:
`Precedence levels
<https://en.wikipedia.org/wiki/Order_of_operations>`_ that are
-implemented in the |Coq| parser are shown in the documentation by
+implemented in the Coq parser are shown in the documentation by
appending the level to the nonterminal name (as in :n:`@term100` or
:n:`@ltac_expr3`).
.. note::
- |Coq| uses an extensible parser. Plugins and the :ref:`notation
+ Coq uses an extensible parser. Plugins and the :ref:`notation
system <syntax-extensions-and-notation-scopes>` can extend the
syntax at run time. Some notations are defined in the :term:`prelude`,
which is loaded by default. The documented grammar doesn't include
@@ -71,8 +71,8 @@ appending the level to the nonterminal name (as in :n:`@term100` or
Given the complexity of these parsing rules, it would be extremely
difficult to create an external program that can properly parse a
- |Coq| document. Therefore, tool writers are advised to delegate
- parsing to |Coq|, by communicating with it, for instance through
+ Coq document. Therefore, tool writers are advised to delegate
+ parsing to Coq, by communicating with it, for instance through
`SerAPI <https://github.com/ejgallego/coq-serapi>`_.
.. seealso:: :cmd:`Print Grammar`
@@ -113,7 +113,7 @@ Identifiers
Numbers
Numbers are sequences of digits with an optional fractional part
- and exponent, optionally preceded by a minus sign. Hexadecimal numerals
+ and exponent, optionally preceded by a minus sign. Hexadecimal numbers
start with ``0x`` or ``0X``. :n:`@bigint` are integers;
numbers without fractional nor exponent parts. :n:`@bignat` are non-negative
integers. Underscores embedded in the digits are ignored, for example
@@ -134,7 +134,7 @@ Numbers
hexdigit ::= {| 0 .. 9 | a .. f | A .. F }
:n:`@integer` and :n:`@natural` are limited to the range that fits
- into an |OCaml| integer (63-bit integers on most architectures).
+ into an OCaml integer (63-bit integers on most architectures).
:n:`@bigint` and :n:`@bignat` have no range limitation.
The :ref:`standard library <thecoqlibrary>` provides some
@@ -152,8 +152,8 @@ Strings
:token:`string`.
Keywords
- The following character sequences are keywords defined in the main |Coq| grammar
- that cannot be used as identifiers (even when starting |Coq| with the `-noinit`
+ The following character sequences are keywords defined in the main Coq grammar
+ that cannot be used as identifiers (even when starting Coq with the `-noinit`
command-line flag)::
_ Axiom CoFixpoint Definition Fixpoint Hypothesis Parameter Prop
@@ -168,8 +168,8 @@ Keywords
keywords.
Other tokens
- The following character sequences are tokens defined in the main |Coq| grammar
- (even when starting |Coq| with the `-noinit` command-line flag)::
+ The following character sequences are tokens defined in the main Coq grammar
+ (even when starting Coq with the `-noinit` command-line flag)::
! #[ % & ' ( () ) * + , - ->
. .( .. ... / : ::= := :> ; < <+ <- <:
@@ -195,7 +195,7 @@ Essential vocabulary
--------------------
This section presents the most essential notions to understand the
-rest of the |Coq| manual: :term:`terms <term>` and :term:`types
+rest of the Coq manual: :term:`terms <term>` and :term:`types
<type>` on the one hand, :term:`commands <command>` and :term:`tactics
<tactic>` on the other hand.
@@ -203,14 +203,14 @@ rest of the |Coq| manual: :term:`terms <term>` and :term:`types
term
- Terms are the basic expressions of |Coq|. Terms can represent
+ Terms are the basic expressions of Coq. Terms can represent
mathematical expressions, propositions and proofs, but also
executable programs and program types.
Here is the top-level syntax of terms. Each of the listed
constructs is presented in a dedicated section. Some of these
constructs (like :n:`@term_forall_or_fun`) are part of the core
- language that the kernel of |Coq| understands and are therefore
+ language that the kernel of Coq understands and are therefore
described in :ref:`this chapter <core-language>`, while
others (like :n:`@term_if`) are language extensions that are
presented in :ref:`the next chapter <extensions>`.
@@ -256,18 +256,18 @@ rest of the |Coq| manual: :term:`terms <term>` and :term:`types
type
- To be valid and accepted by the |Coq| kernel, a term needs an
+ To be valid and accepted by the Coq kernel, a term needs an
associated type. We express this relationship by “:math:`x` *of
type* :math:`T`”, which we write as “:math:`x:T`”. Informally,
“:math:`x:T`” can be thought as “:math:`x` *belongs to*
:math:`T`”.
- The |Coq| kernel is a type checker: it verifies that a term has
+ The Coq kernel is a type checker: it verifies that a term has
the expected type by applying a set of typing rules (see
:ref:`Typing-rules`). If that's indeed the case, we say that the
term is :gdef:`well-typed`.
- A special feature of the |Coq| language is that types can depend
+ A special feature of the Coq language is that types can depend
on terms (we say that the language is `dependently-typed
<https://en.wikipedia.org/wiki/Dependent_type>`_). Because of
this, types and terms share a common syntax. All types are terms,
@@ -289,13 +289,13 @@ rest of the |Coq| manual: :term:`terms <term>` and :term:`types
mathematics alternative to the standard `"set theory"
<https://en.wikipedia.org/wiki/Set_theory>`_: we call such
logical foundations `"type theories"
- <https://en.wikipedia.org/wiki/Type_theory>`_. |Coq| is based on
+ <https://en.wikipedia.org/wiki/Type_theory>`_. Coq is based on
the Calculus of Inductive Constructions, which is a particular
instance of type theory.
sentence
- |Coq| documents are made of a series of sentences that contain
+ Coq documents are made of a series of sentences that contain
:term:`commands <command>` or :term:`tactics <tactic>`, generally
terminated with a period and optionally decorated with
:term:`attributes <attribute>`.
@@ -315,7 +315,7 @@ rest of the |Coq| manual: :term:`terms <term>` and :term:`types
command
- A :production:`command` can be used to modify the state of a |Coq|
+ A :production:`command` can be used to modify the state of a Coq
document, for instance by declaring a new object, or to get
information about the current state.
@@ -334,7 +334,7 @@ rest of the |Coq| manual: :term:`terms <term>` and :term:`types
Tactics specify how to transform the current proof state as a
step in creating a proof. They are syntactically valid only when
- |Coq| is in proof mode, such as after a :cmd:`Theorem` command
+ Coq is in proof mode, such as after a :cmd:`Theorem` command
and before any subsequent proof-terminating command such as
:cmd:`Qed`. See :ref:`proofhandling` for more on proof mode.
@@ -346,10 +346,10 @@ rest of the |Coq| manual: :term:`terms <term>` and :term:`types
Settings
--------
-There are several mechanisms for changing the behavior of |Coq|. The
+There are several mechanisms for changing the behavior of Coq. The
:term:`attribute` mechanism is used to modify the behavior of a single
:term:`sentence`. The :term:`flag`, :term:`option` and :term:`table`
-mechanisms are used to modify the behavior of |Coq| more globally in a
+mechanisms are used to modify the behavior of Coq more globally in a
document or project.
.. _attributes:
@@ -420,7 +420,7 @@ boldface label "Attribute:". Attributes are listed in the
Flags, Options and Tables
~~~~~~~~~~~~~~~~~~~~~~~~~
-The following types of settings can be used to change the behavior of |Coq| in
+The following types of settings can be used to change the behavior of Coq in
subsequent commands and tactics (see :ref:`set_unset_scope_qualifiers` for a
more precise description of the scope of these settings):
@@ -463,10 +463,10 @@ they appear after a boldface label. They are listed in the
This warning message can be raised by :cmd:`Set` and
:cmd:`Unset` when :n:`@setting_name` is unknown. It is a
warning rather than an error because this helps library authors
- produce |Coq| code that is compatible with several |Coq| versions.
+ produce Coq code that is compatible with several Coq versions.
To preserve the same behavior, they may need to set some
compatibility flags or options that did not exist in previous
- |Coq| versions.
+ Coq versions.
.. cmd:: Unset @setting_name
:name: Unset
diff --git a/doc/sphinx/language/core/coinductive.rst b/doc/sphinx/language/core/coinductive.rst
index 0520afd600..3e2ecdc0f0 100644
--- a/doc/sphinx/language/core/coinductive.rst
+++ b/doc/sphinx/language/core/coinductive.rst
@@ -28,8 +28,8 @@ More information on co-inductive definitions can be found in
This command supports the :attr:`universes(polymorphic)`,
:attr:`universes(monomorphic)`, :attr:`universes(template)`,
:attr:`universes(notemplate)`, :attr:`universes(cumulative)`,
- :attr:`universes(noncumulative)` and :attr:`private(matching)`
- attributes.
+ :attr:`universes(noncumulative)`, :attr:`private(matching)`
+ and :attr:`using` attributes.
.. example::
@@ -76,7 +76,7 @@ propositional η-equality, which itself would require full η-conversion for
subject reduction to hold, but full η-conversion is not acceptable as it would
make type checking undecidable.
-Since the introduction of primitive records in |Coq| 8.5, an alternative
+Since the introduction of primitive records in Coq 8.5, an alternative
presentation is available, called *negative co-inductive types*. This consists
in defining a co-inductive type as a primitive record type through its
projections. Such a technique is akin to the *co-pattern* style that can be
@@ -115,7 +115,7 @@ equality:
Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2.
-As of |Coq| 8.9, it is now advised to use negative co-inductive types rather than
+As of Coq 8.9, it is now advised to use negative co-inductive types rather than
their positive counterparts.
.. seealso::
@@ -195,7 +195,7 @@ Top-level definitions of co-recursive functions
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 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`.
diff --git a/doc/sphinx/language/core/conversion.rst b/doc/sphinx/language/core/conversion.rst
index 6b031cfea3..7395b12339 100644
--- a/doc/sphinx/language/core/conversion.rst
+++ b/doc/sphinx/language/core/conversion.rst
@@ -85,7 +85,7 @@ reduction is called δ-reduction and shows as follows.
ζ-reduction
~~~~~~~~~~~
-|Coq| allows also to remove local definitions occurring in terms by
+Coq allows also to remove local definitions occurring in terms by
replacing the defined variable by its value. The declaration being
destroyed, this reduction differs from δ-reduction. It is called
ζ-reduction and shows as follows.
diff --git a/doc/sphinx/language/core/definitions.rst b/doc/sphinx/language/core/definitions.rst
index 8d67a3cf40..79489c85f6 100644
--- a/doc/sphinx/language/core/definitions.rst
+++ b/doc/sphinx/language/core/definitions.rst
@@ -13,15 +13,18 @@ Let-in definitions
.. prodn::
term_let ::= let @name {? : @type } := @term in @term
| let @name {+ @binder } {? : @type } := @term in @term
- | let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term
- | let ' @pattern := @term {? return @term100 } in @term
- | let ' @pattern in @pattern := @term return @term100 in @term
+ | @destructuring_let
-:n:`let @ident := @term in @term’`
-denotes the local binding of :n:`@term` to the variable
-:n:`@ident` in :n:`@term`’. There is a syntactic sugar for let-in
-definition of functions: :n:`let @ident {+ @binder} := @term in @term’`
-stands for :n:`let @ident := fun {+ @binder} => @term in @term’`.
+:n:`let @ident := @term__1 in @term__2` represents the local binding of
+the variable :n:`@ident` to the value :n:`@term__1` in :n:`@term__2`.
+
+:n:`let @ident {+ @binder} := @term__1 in @term__2` is an abbreviation
+for :n:`let @ident := fun {+ @binder} => @term__1 in @term__2`.
+
+.. seealso::
+
+ Extensions of the `let ... in ...` syntax are described in
+ :ref:`irrefutable-patterns`.
.. index::
single: ... : ... (type cast)
@@ -87,10 +90,10 @@ Section :ref:`typing-rules`.
computation on :n:`@term`.
These commands also support the :attr:`universes(polymorphic)`,
- :attr:`universes(monomorphic)`, :attr:`program` (see :ref:`program_definition`) and
- :attr:`canonical` attributes.
+ :attr:`universes(monomorphic)`, :attr:`program` (see :ref:`program_definition`),
+ :attr:`canonical` and :attr:`using` attributes.
- If :n:`@term` is omitted, :n:`@type` is required and |Coq| enters 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`.
@@ -135,7 +138,7 @@ Chapter :ref:`Tactics`. The basic assertion command is:
| Proposition
| Property
- After the statement is asserted, |Coq| needs a proof. Once a proof of
+ After the statement is asserted, Coq needs a proof. Once a proof of
:n:`@type` under the assumptions represented by :n:`@binder`\s is given and
validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and
the theorem is bound to the name :n:`@ident` in the environment.
@@ -159,6 +162,8 @@ Chapter :ref:`Tactics`. The basic assertion command is:
correct at some time of the interactive development of a proof, use the
command :cmd:`Guarded`.
+ This command accepts the :attr:`using` attribute.
+
.. exn:: The term @term has type @type which should be Set, Prop or Type.
:undocumented:
@@ -174,7 +179,7 @@ Chapter :ref:`Tactics`. The basic assertion command is:
This feature, called nested proofs, is disabled by default.
To activate it, turn the :flag:`Nested Proofs Allowed` flag on.
-Proofs start with the keyword :cmd:`Proof`. Then |Coq| enters the proof editing mode
+Proofs start with the keyword :cmd:`Proof`. Then Coq enters the proof editing mode
until the proof is completed. In proof editing mode, the user primarily enters
tactics, which are described in chapter :ref:`Tactics`. The user may also enter
commands to manage the proof editing mode. They are described in Chapter
diff --git a/doc/sphinx/language/core/index.rst b/doc/sphinx/language/core/index.rst
index c7b1df28db..de780db267 100644
--- a/doc/sphinx/language/core/index.rst
+++ b/doc/sphinx/language/core/index.rst
@@ -4,7 +4,7 @@
Core language
=============
-At the heart of the |Coq| proof assistant is the |Coq| kernel. While
+At the heart of the Coq proof assistant is the Coq kernel. While
users have access to a language with many convenient features such as
:ref:`notations <syntax-extensions-and-notation-scopes>`,
:ref:`implicit arguments <ImplicitArguments>`, etc. (presented in the
diff --git a/doc/sphinx/language/core/inductive.rst b/doc/sphinx/language/core/inductive.rst
index ba0ec28f8b..d3bd787587 100644
--- a/doc/sphinx/language/core/inductive.rst
+++ b/doc/sphinx/language/core/inductive.rst
@@ -17,7 +17,7 @@ Inductive types
constructor ::= @ident {* @binder } {? @of_type }
This command defines one or more
- inductive types and its constructors. |Coq| generates destructors
+ inductive types and its constructors. Coq generates destructors
depending on the universe that the inductive type belongs to.
The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``,
@@ -411,11 +411,13 @@ constructions.
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 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`.
+ This command accepts the :attr:`using` attribute.
+
.. note::
+ Some fixpoints may have several arguments that fit as decreasing
@@ -550,7 +552,7 @@ the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort`
\end{array}
\right]}
- which corresponds to the result of the |Coq| declaration:
+ which corresponds to the result of the Coq declaration:
.. coqtop:: in reset
@@ -571,7 +573,7 @@ the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort`
\consf &:& \tree → \forest → \forest\\
\end{array}\right]}
- which corresponds to the result of the |Coq| declaration:
+ which corresponds to the result of the Coq declaration:
.. coqtop:: in
@@ -594,7 +596,7 @@ the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort`
\oddS &:& ∀ n,~\even~n → \odd~(\nS~n)
\end{array}\right]}
- which corresponds to the result of the |Coq| declaration:
+ which corresponds to the result of the Coq declaration:
.. coqtop:: in
@@ -1097,7 +1099,7 @@ Conversion is preserved as any (partial) instance :math:`I_j~q_1 … q_r` or
template polymorphic, even if the :flag:`Auto Template
Polymorphism` flag is on.
-In practice, the rule **Ind-Family** is used by |Coq| only when all the
+In practice, the rule **Ind-Family** is used by Coq only when all the
inductive types of the inductive definition are declared with an arity
whose sort is in the Type hierarchy. Then, the polymorphism is over
the parameters whose type is an arity of sort in the Type hierarchy.
@@ -1235,7 +1237,7 @@ at the computational level it implements a generic operator for doing
primitive recursion over the structure.
But this operator is rather tedious to implement and use. We choose in
-this version of |Coq| to factorize the operator for primitive recursion
+this version of Coq to factorize the operator for primitive recursion
into two more primitive operations as was first suggested by Th.
Coquand in :cite:`Coq92`. One is the definition by pattern matching. The
second one is a definition by guarded fixpoints.
@@ -1250,7 +1252,7 @@ The basic idea of this operator is that we have an object :math:`m` in an
inductive type :math:`I` and we want to prove a property which possibly
depends on :math:`m`. For this, it is enough to prove the property for
:math:`m = (c_i~u_1 … u_{p_i} )` for each constructor of :math:`I`.
-The |Coq| term for this proof
+The Coq term for this proof
will be written:
.. math::
@@ -1265,7 +1267,7 @@ Actually, for type checking a :math:`\Match…\with…\kwend` expression we also
to know the predicate :math:`P` to be proved by case analysis. In the general
case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate
over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I`
-(parameters excluded), and the last one corresponds to object :math:`m`. |Coq|
+(parameters excluded), and the last one corresponds to object :math:`m`. Coq
can sometimes infer this predicate but sometimes not. The concrete
syntax for describing this predicate uses the :math:`\as…\In…\return`
construction. For instance, let us assume that :math:`I` is an unary predicate
diff --git a/doc/sphinx/language/core/modules.rst b/doc/sphinx/language/core/modules.rst
index 1309a47ff4..54252689e1 100644
--- a/doc/sphinx/language/core/modules.rst
+++ b/doc/sphinx/language/core/modules.rst
@@ -864,17 +864,17 @@ Libraries and qualified names
Names of libraries
~~~~~~~~~~~~~~~~~~
-The theories developed in |Coq| are stored in *library files* which are
+The theories developed in Coq are stored in *library files* which are
hierarchically classified into *libraries* and *sublibraries*. To
express this hierarchy, library names are represented by qualified
identifiers qualid, i.e. as list of identifiers separated by dots (see
:ref:`qualified-names`). For instance, the library file ``Mult`` of the standard
-|Coq| library ``Arith`` is named ``Coq.Arith.Mult``. The identifier that starts
+Coq library ``Arith`` is named ``Coq.Arith.Mult``. The identifier that starts
the name of a library is called a *library root*. All library files of
-the standard library of |Coq| have the reserved root |Coq| but library
-filenames based on other roots can be obtained by using |Coq| commands
+the standard library of Coq have the reserved root Coq but library
+filenames based on other roots can be obtained by using Coq commands
(coqc, coqtop, coqdep, …) options ``-Q`` or ``-R`` (see :ref:`command-line-options`).
-Also, when an interactive |Coq| session starts, a library of root ``Top`` is
+Also, when an interactive Coq session starts, a library of root ``Top`` is
started, unless option ``-top`` or ``-notop`` is set (see :ref:`command-line-options`).
.. _qualified-names:
@@ -897,7 +897,7 @@ followed by the sequence of submodules names encapsulating the
construction and ended by the proper name of the construction.
Typically, the absolute name ``Coq.Init.Logic.eq`` denotes Leibniz’
equality defined in the module Logic in the sublibrary ``Init`` of the
-standard library of |Coq|.
+standard library of Coq.
The proper name that ends the name of a construction is the short name
(or sometimes base name) of the construction (for instance, the short
@@ -906,7 +906,7 @@ name is a *partially qualified name* (e.g. ``Logic.eq`` is a partially
qualified name for ``Coq.Init.Logic.eq``). Especially, the short name of a
construction is its shortest partially qualified name.
-|Coq| does not accept two constructions (definition, theorem, …) with
+Coq does not accept two constructions (definition, theorem, …) with
the same absolute name but different constructions can have the same
short name (or even same partially qualified names as soon as the full
names are different).
@@ -916,14 +916,14 @@ names also applies to library filenames.
**Visibility**
-|Coq| maintains a table called the name table which maps partially qualified
+Coq maintains a table called the name table which maps partially qualified
names of constructions to absolute names. This table is updated by the
commands :cmd:`Require`, :cmd:`Import` and :cmd:`Export` and
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 with the :attr:`local` attribute 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
@@ -953,13 +953,13 @@ accessible, absolute names can never be hidden.
Libraries and filesystem
~~~~~~~~~~~~~~~~~~~~~~~~
-.. note:: The questions described here have been subject to redesign in |Coq| 8.5.
- Former versions of |Coq| use the same terminology to describe slightly different things.
+.. note:: The questions described here have been subject to redesign in Coq 8.5.
+ Former versions of Coq use the same terminology to describe slightly different things.
Compiled files (``.vo`` and ``.vio``) store sub-libraries. In order to refer
-to them inside |Coq|, a translation from file-system names to |Coq| names
+to them inside Coq, a translation from file-system names to Coq names
is needed. In this translation, names in the file system are called
-*physical* paths while |Coq| names are contrastingly called *logical*
+*physical* paths while Coq names are contrastingly called *logical*
names.
A logical prefix Lib can be associated with a physical path using
@@ -967,7 +967,7 @@ the command line option ``-Q`` `path` ``Lib``. All subfolders of path are
recursively associated to the logical path ``Lib`` extended with the
corresponding suffix coming from the physical path. For instance, the
folder ``path/fOO/Bar`` maps to ``Lib.fOO.Bar``. Subdirectories corresponding
-to invalid |Coq| identifiers are skipped, and, by convention,
+to invalid Coq identifiers are skipped, and, by convention,
subdirectories named ``CVS`` or ``_darcs`` are skipped too.
Thanks to this mechanism, ``.vo`` files are made available through the
@@ -979,7 +979,7 @@ its logical name, so that an error is issued if it is loaded with the
wrong loadpath afterwards.
Some folders have a special status and are automatically put in the
-path. |Coq| commands associate automatically a logical path to files in
+path. Coq commands associate automatically a logical path to files in
the repository trees rooted at the directory from where the command is
launched, ``coqlib/user-contrib/``, the directories listed in the
``$COQPATH``, ``${XDG_DATA_HOME}/coq/`` and ``${XDG_DATA_DIRS}/coq/``
@@ -1001,12 +1001,12 @@ of the ``Require`` command can be used to bypass the implicit shortening
by providing an absolute root to the required file (see :ref:`compiled-files`).
There also exists another independent loadpath mechanism attached to
-|OCaml| object files (``.cmo`` or ``.cmxs``) rather than |Coq| object
-files as described above. The |OCaml| loadpath is managed using
-the option ``-I`` `path` (in the |OCaml| world, there is neither a
+OCaml object files (``.cmo`` or ``.cmxs``) rather than Coq object
+files as described above. The OCaml loadpath is managed using
+the option ``-I`` `path` (in the OCaml world, there is neither a
notion of logical name prefix nor a way to access files in
subdirectories of path). See the command :cmd:`Declare ML Module` in
-:ref:`compiled-files` to understand the need of the |OCaml| loadpath.
+:ref:`compiled-files` to understand the need of the OCaml loadpath.
-See :ref:`command-line-options` for a more general view over the |Coq| command
+See :ref:`command-line-options` for a more general view over the Coq command
line options.
diff --git a/doc/sphinx/language/core/primitive.rst b/doc/sphinx/language/core/primitive.rst
index 17f569ca2a..4505fc4b4d 100644
--- a/doc/sphinx/language/core/primitive.rst
+++ b/doc/sphinx/language/core/primitive.rst
@@ -45,13 +45,13 @@ applications of these primitive operations.
The extraction of these primitives can be customized similarly to the extraction
of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlInt63`
-module can be used when extracting to |OCaml|: it maps the |Coq| primitives to types
-and functions of a :g:`Uint63` module. That |OCaml| module is not produced by
+module can be used when extracting to OCaml: it maps the Coq primitives to types
+and functions of a :g:`Uint63` module. That OCaml module is not produced by
extraction. Instead, it has to be provided by the user (if they want to compile
or execute the extracted code). For instance, an implementation of this module
-can be taken from the kernel of |Coq|.
+can be taken from the kernel of Coq.
-Literal values (at type :g:`Int63.int`) are extracted to literal |OCaml| values
+Literal values (at type :g:`Int63.int`) are extracted to literal OCaml values
wrapped into the :g:`Uint63.of_int` (resp. :g:`Uint63.of_int64`) constructor on
64-bit (resp. 32-bit) platforms. Currently, this cannot be customized (see the
function :g:`Uint63.compile` from the kernel).
@@ -94,13 +94,13 @@ to comply with the IEEE 754 standard for floating-point arithmetic.
The extraction of these primitives can be customized similarly to the extraction
of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlFloats`
-module can be used when extracting to |OCaml|: it maps the |Coq| primitives to types
-and functions of a :g:`Float64` module. Said |OCaml| module is not produced by
+module can be used when extracting to OCaml: it maps the Coq primitives to types
+and functions of a :g:`Float64` module. Said OCaml module is not produced by
extraction. Instead, it has to be provided by the user (if they want to compile
or execute the extracted code). For instance, an implementation of this module
-can be taken from the kernel of |Coq|.
+can be taken from the kernel of Coq.
-Literal values (of type :g:`Float64.t`) are extracted to literal |OCaml|
+Literal values (of type :g:`Float64.t`) are extracted to literal OCaml
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)`.
@@ -144,19 +144,19 @@ operations.
The extraction of these primitives can be customized similarly to the extraction
of regular axioms (see :ref:`extraction`). Nonetheless, the :g:`ExtrOCamlPArray`
-module can be used when extracting to |OCaml|: it maps the |Coq| primitives to types
-and functions of a :g:`Parray` module. Said |OCaml| module is not produced by
+module can be used when extracting to OCaml: it maps the Coq primitives to types
+and functions of a :g:`Parray` module. Said OCaml module is not produced by
extraction. Instead, it has to be provided by the user (if they want to compile
or execute the extracted code). For instance, an implementation of this module
-can be taken from the kernel of |Coq| (see ``kernel/parray.ml``).
+can be taken from the kernel of Coq (see ``kernel/parray.ml``).
-|Coq|'s primitive arrays are persistent data structures. Semantically, a set operation
+Coq's primitive arrays are persistent data structures. Semantically, a set operation
``t.[i <- a]`` represents a new array that has the same values as ``t``, except
at position ``i`` where its value is ``a``. The array ``t`` still exists, can
still be used and its values were not modified. Operationally, the implementation
-of |Coq|'s primitive arrays is optimized so that the new array ``t.[i <- a]`` does not
+of Coq's primitive arrays is optimized so that the new array ``t.[i <- a]`` does not
copy all of ``t``. The details are in section 2.3 of :cite:`ConchonFilliatre07wml`.
-In short, the implementation keeps one version of ``t`` as an |OCaml| native array and
+In short, the implementation keeps one version of ``t`` as an OCaml native array and
other versions as lists of modifications to ``t``. Accesses to the native array
version are constant time operations. However, accesses to versions where all the cells of
the array are modified have O(n) access time, the same as a list. The version that is kept as the native array
diff --git a/doc/sphinx/language/core/sections.rst b/doc/sphinx/language/core/sections.rst
index c70f7a347b..df50dbafe3 100644
--- a/doc/sphinx/language/core/sections.rst
+++ b/doc/sphinx/language/core/sections.rst
@@ -84,7 +84,7 @@ Sections create local contexts which can be shared across multiple definitions.
will be wrapped with a :n:`@term_let` with the same declaration.
As for :cmd:`Definition`, :cmd:`Fixpoint` and :cmd:`CoFixpoint`,
- if :n:`@term` is omitted, :n:`@type` is required and |Coq| enters 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`.
diff --git a/doc/sphinx/language/extensions/arguments-command.rst b/doc/sphinx/language/extensions/arguments-command.rst
index 29877e1b32..2460461ede 100644
--- a/doc/sphinx/language/extensions/arguments-command.rst
+++ b/doc/sphinx/language/extensions/arguments-command.rst
@@ -86,6 +86,7 @@ Setting properties of a function's arguments
the parameter name used in the function definition). Unless `rename` is specified,
the list of :n:`@name`\s must be a prefix of the formal parameters, including all implicit
arguments. `_` can be used to skip over a formal parameter.
+ The construct :n:`@name {? % @scope }` declares :n:`@name` as non-implicit if `clear implicits` is specified or at least one other name is declared implicit in the same list of :n:`@name`\s.
:token:`scope` can be either a scope name or its delimiting key. See :ref:`binding_to_scope`.
`clear implicits`
@@ -181,7 +182,7 @@ Manual declaration of implicit arguments
Automatic declaration of implicit arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The ":n:`default implicits`" :token:`args_modifier` clause tells |Coq| to automatically determine the
+ The ":n:`default implicits`" :token:`args_modifier` clause tells Coq to automatically determine the
implicit arguments of the object.
Auto-detection is governed by flags specifying whether strict,
@@ -377,7 +378,7 @@ Effects of :cmd:`Arguments` on unfolding
Bidirectionality hints
~~~~~~~~~~~~~~~~~~~~~~
-When type-checking an application, |Coq| normally does not use information from
+When type-checking an application, Coq normally does not use information from
the context to infer the types of the arguments. It only checks after the fact
that the type inferred for the application is coherent with the expected type.
Bidirectionality hints make it possible to specify that after type-checking the
@@ -394,7 +395,7 @@ the context to help inferring the types of the remaining arguments.
* *type inference*, with is inferring the type of a construct by analyzing the construct.
Methods that combine these approaches are known as *bidirectional typing*.
- |Coq| normally uses only the first approach to infer the types of arguments,
+ Coq normally uses only the first approach to infer the types of arguments,
then later verifies that the inferred type is consistent with the expected type.
*Bidirectionality hints* specify to use both methods: after type checking the
first arguments of an application (appearing before the `&` in :cmd:`Arguments`),
@@ -416,7 +417,7 @@ type check the remaining arguments (in :n:`@arg_specs__2`).
Definition b2n (b : bool) := if b then 1 else 0.
Coercion b2n : bool >-> nat.
- |Coq| cannot automatically coerce existential statements over ``bool`` to
+ Coq cannot automatically coerce existential statements over ``bool`` to
statements over ``nat``, because the need for inserting a coercion is known
only from the expected type of a subterm:
@@ -431,7 +432,7 @@ type check the remaining arguments (in :n:`@arg_specs__2`).
Arguments ex_intro _ _ & _ _.
Check (ex_intro _ true _ : exists n : nat, n > 0).
-|Coq| will attempt to produce a term which uses the arguments you
+Coq will attempt to produce a term which uses the arguments you
provided, but in some cases involving Program mode the arguments after
the bidirectionality starts may be replaced by convertible but
syntactically different terms.
diff --git a/doc/sphinx/language/extensions/canonical.rst b/doc/sphinx/language/extensions/canonical.rst
index 38c9fa336d..48120503af 100644
--- a/doc/sphinx/language/extensions/canonical.rst
+++ b/doc/sphinx/language/extensions/canonical.rst
@@ -159,7 +159,7 @@ of the terms that are compared.
End theory.
End EQ.
-We use |Coq| modules as namespaces. This allows us to follow the same
+We use Coq modules as namespaces. This allows us to follow the same
pattern and naming convention for the rest of the chapter. The base
namespace contains the definitions of the algebraic structure. To
keep the example small, the algebraic structure ``EQ.type`` we are
@@ -196,7 +196,7 @@ We amend that by equipping ``nat`` with a comparison relation.
Check 3 == 3.
Eval compute in 3 == 4.
-This last test shows that |Coq| is now not only able to type check ``3 == 3``,
+This last test shows that Coq is now not only able to type check ``3 == 3``,
but also that the infix relation was bound to the ``nat_eq`` relation.
This relation is selected whenever ``==`` is used on terms of type nat.
This can be read in the line declaring the canonical structure
@@ -223,8 +223,8 @@ example work:
Fail Check forall (e : EQ.type) (a b : EQ.obj e), (a, b) == (a, b).
-The error message is telling that |Coq| has no idea on how to compare
-pairs of objects. The following construction is telling |Coq| exactly
+The error message is telling that Coq has no idea on how to compare
+pairs of objects. The following construction is telling Coq exactly
how to do that.
.. coqtop:: all
@@ -241,7 +241,7 @@ how to do that.
Check forall n m : nat, (3, 4) == (n, m).
-Thanks to the ``pair_EQty`` declaration, |Coq| is able to build a comparison
+Thanks to the ``pair_EQty`` declaration, Coq is able to build a comparison
relation for pairs whenever it is able to build a comparison relation
for each component of the pair. The declaration associates to the key ``*``
(the type constructor of pairs) the canonical comparison
@@ -290,7 +290,7 @@ As before we register a canonical ``LE`` class for ``nat``.
Canonical Structure nat_LEty : LE.type := LE.Pack nat nat_LEcl.
-And we enable |Coq| to relate pair of terms with ``<=``.
+And we enable Coq to relate pair of terms with ``<=``.
.. coqtop:: all
@@ -355,10 +355,10 @@ theory of this new class.
The problem is that the two classes ``LE`` and ``LEQ`` are not yet related by
-a subclass relation. In other words |Coq| does not see that an object of
+a subclass relation. In other words Coq does not see that an object of
the ``LEQ`` class is also an object of the ``LE`` class.
-The following two constructions tell |Coq| how to canonically build the
+The following two constructions tell Coq how to canonically build the
``LE.type`` and ``EQ.type`` structure given an ``LEQ.type`` structure on the same
type.
@@ -413,7 +413,7 @@ setting to any concrete instate of the algebraic structure.
Abort.
-Again one has to tell |Coq| that the type ``nat`` is in the ``LEQ`` class, and
+Again one has to tell Coq that the type ``nat`` is in the ``LEQ`` class, and
how the type constructor ``*`` interacts with the ``LEQ`` class. In the
following proofs are omitted for brevity.
@@ -468,7 +468,7 @@ Note that no direct proof of ``n <= m -> m <= n -> n == m`` is provided by
the user for ``n`` and m of type ``nat * nat``. What the user provides is a
proof of this statement for ``n`` and ``m`` of type ``nat`` and a proof that the
pair constructor preserves this property. The combination of these two
-facts is a simple form of proof search that |Coq| performs automatically
+facts is a simple form of proof search that Coq performs automatically
while inferring canonical structures.
Compact declaration of Canonical Structures
@@ -507,7 +507,7 @@ instances: ``[find e | EQ.obj e ~ T | "is not an EQ.type" ]``. It should be
read as: “find a class e such that its objects have type T or fail
with message "T is not an EQ.type"”.
-The other utilities are used to ask |Coq| to solve a specific unification
+The other utilities are used to ask Coq to solve a specific unification
problem, that will in turn require the inference of some canonical structures.
They are explained in more details in :cite:`CSwcu`.
@@ -532,7 +532,7 @@ The object ``Pack`` takes a type ``T`` (the key) and a mixin ``m``. It infers al
the other pieces of the class ``LEQ`` and declares them as canonical
values associated to the ``T`` key. All in all, the only new piece of
information we add in the ``LEQ`` class is the mixin, all the rest is
-already canonical for ``T`` and hence can be inferred by |Coq|.
+already canonical for ``T`` and hence can be inferred by Coq.
``Pack`` is a notation, hence it is not type checked at the time of its
declaration. It will be type checked when it is used, an in that case ``T`` is
diff --git a/doc/sphinx/language/extensions/evars.rst b/doc/sphinx/language/extensions/evars.rst
index dc208a63a0..fd9695e270 100644
--- a/doc/sphinx/language/extensions/evars.rst
+++ b/doc/sphinx/language/extensions/evars.rst
@@ -13,7 +13,7 @@ Existential variables
| ?[ ?@ident ]
| ?@ident {? @%{ {+; @ident := @term } %} }
-|Coq| terms can include existential variables that represent unknown
+Coq terms can include existential variables that represent unknown
subterms that are eventually replaced with actual subterms.
Existential variables are generated in place of unsolved implicit
@@ -68,7 +68,7 @@ Inferable subterms
~~~~~~~~~~~~~~~~~~
Expressions often contain redundant pieces of information. Subterms that can be
-automatically inferred by |Coq| can be replaced by the symbol ``_`` and |Coq| will
+automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will
guess the missing piece of information.
.. extracted from Gallina extensions chapter
diff --git a/doc/sphinx/language/extensions/implicit-arguments.rst b/doc/sphinx/language/extensions/implicit-arguments.rst
index 9457505feb..23ba5f703a 100644
--- a/doc/sphinx/language/extensions/implicit-arguments.rst
+++ b/doc/sphinx/language/extensions/implicit-arguments.rst
@@ -115,7 +115,7 @@ application will include that argument. Otherwise, the argument is
*non-maximally inserted* and the partial application will not include that argument.
Each implicit argument can be declared to be inserted maximally or non
-maximally. In |Coq|, maximally inserted implicit arguments are written between curly braces
+maximally. In Coq, maximally inserted implicit arguments are written between curly braces
"{ }" and non-maximally inserted implicit arguments are written in square brackets "[ ]".
.. seealso:: :flag:`Maximal Implicit Insertion`
@@ -146,7 +146,7 @@ by replacing it with `_`.
.. exn:: Cannot infer a term for this placeholder.
:name: Cannot infer a term for this placeholder. (Casual use of implicit arguments)
- |Coq| was not able to deduce an instantiation of a “_”.
+ Coq was not able to deduce an instantiation of a “_”.
.. _declare-implicit-args:
@@ -290,8 +290,8 @@ Controlling contextual implicit arguments
.. flag:: Contextual Implicit
- By default, |Coq| does not automatically set implicit the contextual
- implicit arguments. You can turn this flag on to tell |Coq| to also
+ By default, Coq does not automatically set implicit the contextual
+ implicit arguments. You can turn this flag on to tell Coq to also
infer contextual implicit argument.
.. _controlling-rev-pattern-implicit-args:
@@ -301,8 +301,8 @@ Controlling reversible-pattern implicit arguments
.. flag:: Reversible Pattern Implicit
- By default, |Coq| does not automatically set implicit the reversible-pattern
- implicit arguments. You can turn this flag on to tell |Coq| to also infer
+ By default, Coq does not automatically set implicit the reversible-pattern
+ implicit arguments. You can turn this flag on to tell Coq to also infer
reversible-pattern implicit argument.
.. _controlling-insertion-implicit-args:
diff --git a/doc/sphinx/language/extensions/index.rst b/doc/sphinx/language/extensions/index.rst
index ea7271179e..ed207ca743 100644
--- a/doc/sphinx/language/extensions/index.rst
+++ b/doc/sphinx/language/extensions/index.rst
@@ -4,7 +4,7 @@
Language extensions
===================
-Elaboration extends the language accepted by the |Coq| kernel to make it
+Elaboration extends the language accepted by the Coq kernel to make it
easier to use. For example, this lets the user omit most type
annotations because they can be inferred, call functions with implicit
arguments which will be inferred as well, extend the syntax with
diff --git a/doc/sphinx/language/extensions/match.rst b/doc/sphinx/language/extensions/match.rst
index 3c1983ee97..8e62c2af13 100644
--- a/doc/sphinx/language/extensions/match.rst
+++ b/doc/sphinx/language/extensions/match.rst
@@ -5,7 +5,7 @@ Extended pattern matching
:Authors: Cristina Cornes and Hugo Herbelin
-This section describes the full form of pattern matching in |Coq| terms.
+This section describes the full form of pattern matching in Coq terms.
.. |rhs| replace:: right hand sides
@@ -86,6 +86,13 @@ Pattern-matching on terms inhabiting inductive type having only one
constructor can be alternatively written using :g:`let … in …`
constructions. There are two variants of them.
+.. insertprodn destructuring_let destructuring_let
+
+.. prodn::
+ destructuring_let ::= let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term
+ | let ' @pattern := @term {? return @term100 } in @term
+ | let ' @pattern in @pattern := @term return @term100 in @term
+
First destructuring let syntax
++++++++++++++++++++++++++++++
@@ -187,10 +194,10 @@ Printing nested patterns
pattern matching into a single pattern matching over a nested
pattern.
- When this flag is on (default), |Coq|’s printer tries to do such
+ When this flag is on (default), Coq’s printer tries to do such
limited re-factorization.
- Turning it off tells |Coq| to print only simple pattern matching problems
- in the same way as the |Coq| kernel handles them.
+ Turning it off tells Coq to print only simple pattern matching problems
+ in the same way as the Coq kernel handles them.
Factorization of clauses with same right-hand side
@@ -200,7 +207,7 @@ Factorization of clauses with same right-hand side
When several patterns share the same right-hand side, it is additionally
possible to share the clauses using disjunctive patterns. Assuming that the
- printing matching mode is on, this flag (on by default) tells |Coq|'s
+ printing matching mode is on, this flag (on by default) tells Coq's
printer to try to do this kind of factorization.
Use of a default clause
@@ -212,7 +219,7 @@ Use of a default clause
arguments of the patterns, yet an extra factorization is possible: the
disjunction of patterns can be replaced with a `_` default clause. Assuming that
the printing matching mode and the factorization mode are on, this flag (on by
- default) tells |Coq|'s printer to use a default clause when relevant.
+ default) tells Coq's printer to use a default clause when relevant.
Printing of wildcard patterns
++++++++++++++++++++++++++++++
@@ -234,7 +241,7 @@ Printing of the elimination predicate
In most of the cases, the type of the result of a matched term is
mechanically synthesizable. Especially, if the result type does not
depend of the matched term. When this flag is on (default),
- the result type is not printed when |Coq| knows that it can re-
+ the result type is not printed when Coq knows that it can re-
synthesize it.
@@ -676,7 +683,7 @@ Dependent pattern matching
~~~~~~~~~~~~~~~~~~~~~~~~~~
The examples given so far do not need an explicit elimination
-predicate because all the |rhs| have the same type and |Coq|
+predicate because all the |rhs| have the same type and Coq
succeeds to synthesize it. Unfortunately when dealing with dependent
patterns it often happens that we need to write cases where the types
of the |rhs| are different instances of the elimination predicate. The
diff --git a/doc/sphinx/practical-tools/coq-commands.rst b/doc/sphinx/practical-tools/coq-commands.rst
index 59e1c65a49..d20a82e6c0 100644
--- a/doc/sphinx/practical-tools/coq-commands.rst
+++ b/doc/sphinx/practical-tools/coq-commands.rst
@@ -1,13 +1,13 @@
.. _thecoqcommands:
-The |Coq| commands
+The Coq commands
====================
-There are three |Coq| commands:
+There are three Coq commands:
-+ ``coqtop``: the |Coq| toplevel (interactive mode);
-+ ``coqc``: the |Coq| compiler (batch compilation);
-+ ``coqchk``: the |Coq| checker (validation of compiled libraries).
++ ``coqtop``: the Coq toplevel (interactive mode);
++ ``coqc``: the Coq compiler (batch compilation);
++ ``coqchk``: the Coq checker (validation of compiled libraries).
The options are (basically) the same for the first two commands, and
@@ -19,19 +19,19 @@ roughly described below. You can also look at the ``man`` pages of
Interactive use (coqtop)
------------------------
-In the interactive mode, also known as the |Coq| toplevel, the user can
-develop his theories and proofs step by step. The |Coq| toplevel is run
+In the interactive mode, also known as the Coq toplevel, the user can
+develop his theories and proofs step by step. The Coq toplevel is run
by the command ``coqtop``.
-There are two different binary images of |Coq|: the byte-code one and the
-native-code one (if |OCaml| provides a native-code compiler for
+There are two different binary images of Coq: the byte-code one and the
+native-code one (if OCaml provides a native-code compiler for
your platform, which is supposed in the following). By default,
``coqtop`` executes the native-code version; run ``coqtop.byte`` to get
the byte-code version.
-The byte-code toplevel is based on an |OCaml| toplevel (to
-allow dynamic linking of tactics). You can switch to the |OCaml| toplevel
-with the command ``Drop.``, and come back to the |Coq|
+The byte-code toplevel is based on an OCaml toplevel (to
+allow dynamic linking of tactics). You can switch to the OCaml toplevel
+with the command ``Drop.``, and come back to the Coq
toplevel with the command ``Coqloop.loop();;``.
.. flag:: Coqtop Exit On Error
@@ -48,7 +48,7 @@ vernacular file named *file*.v, and tries to compile it into a
.. caution::
- The name *file* should be a regular |Coq| identifier as defined in Section :ref:`lexical-conventions`.
+ The name *file* should be a regular Coq identifier as defined in Section :ref:`lexical-conventions`.
It should contain only letters, digits or underscores (_). For example ``/bar/foo/toto.v`` is valid,
but ``/bar/foo/to-to.v`` is not.
@@ -59,9 +59,9 @@ Customization at launch time
By resource file
~~~~~~~~~~~~~~~~~~~~~~~
-When |Coq| is launched, with either ``coqtop`` or ``coqc``, the
+When Coq is launched, with either ``coqtop`` or ``coqc``, the
resource file ``$XDG_CONFIG_HOME/coq/coqrc.xxx``, if it exists, will
-be implicitly prepended to any document read by |Coq|, whether it is an
+be implicitly prepended to any document read by Coq, whether it is an
interactive session or a file to compile. Here, ``$XDG_CONFIG_HOME``
is the configuration directory of the user (by default it's ``~/.config``)
and ``xxx`` is the version number (e.g. 8.8). If
@@ -73,7 +73,7 @@ You can also specify an arbitrary name for the resource file
(see option ``-init-file`` below).
The resource file may contain, for instance, ``Add LoadPath`` commands to add
-directories to the load path of |Coq|. It is possible to skip the
+directories to the load path of Coq. It is possible to skip the
loading of the resource file with the option ``-q``.
.. _customization-by-environment-variables:
@@ -82,10 +82,10 @@ By environment variables
~~~~~~~~~~~~~~~~~~~~~~~~~
``$COQPATH`` can be used to specify the load path. It is a list of directories separated by
-``:`` (``;`` on Windows). |Coq| will also honor ``$XDG_DATA_HOME`` and
+``:`` (``;`` on Windows). Coq will also honor ``$XDG_DATA_HOME`` and
``$XDG_DATA_DIRS`` (see Section :ref:`libraries-and-filesystem`).
-Some |Coq| commands call other |Coq| commands. In this case, they look for
+Some Coq commands call other Coq commands. In this case, they look for
the commands in directory specified by ``$COQBIN``. If this variable is
not set, they look for the commands in the executable path.
@@ -115,7 +115,7 @@ can be used to specify certain runtime and memory usage parameters. In most cas
experimenting with these settings will likely not cause a significant performance difference
and should be harmless.
-If the variable is not set, |Coq| uses the
+If the variable is not set, Coq uses the
`default values <https://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#TYPEcontrol>`_,
except that ``space_overhead`` is set to 120 and ``minor_heap_size`` is set to 32Mwords
(256MB with 64-bit executables or 128MB with 32-bit executables).
@@ -133,21 +133,21 @@ The following command-line options are recognized by the commands ``coqc``
and ``coqtop``, unless stated otherwise:
:-I *directory*, -include *directory*: Add physical path *directory*
- to the |OCaml| loadpath.
+ to the OCaml loadpath.
.. seealso::
:ref:`names-of-libraries` and the
command Declare ML Module Section :ref:`compiled-files`.
:-Q *directory* *dirpath*: Add physical path *directory* to the list of
- directories where |Coq| looks for a file and bind it to the logical
+ directories where Coq looks for a file and bind it to the logical
directory *dirpath*. The subdirectory structure of *directory* is
- recursively available from |Coq| using absolute names (extending the
+ recursively available from Coq using absolute names (extending the
:n:`@dirpath` prefix) (see Section :ref:`qualified-names`). Note that only those
subdirectories and files which obey the lexical conventions of what is
an :n:`@ident` are taken into account. Conversely, the
underlying file systems or operating systems may be more restrictive
- than |Coq|. While Linux’s ext4 file system supports any |Coq| recursive
+ than Coq. While Linux’s ext4 file system supports any Coq recursive
layout (within the limit of 255 bytes per filename), the default on
NTFS (Windows) or HFS+ (MacOS X) file systems is on the contrary to
disallow two files differing only in the case in the same directory.
@@ -155,7 +155,7 @@ and ``coqtop``, unless stated otherwise:
.. seealso:: Section :ref:`names-of-libraries`.
:-R *directory* *dirpath*: Do as ``-Q`` *directory* *dirpath* but make the
subdirectory structure of *directory* recursively visible so that the
- recursive contents of physical *directory* is available from |Coq| using
+ recursive contents of physical *directory* is available from Coq using
short or partially qualified names.
.. seealso:: Section :ref:`names-of-libraries`.
@@ -172,12 +172,12 @@ and ``coqtop``, unless stated otherwise:
loading the default resource file from the standard configuration
directories.
:-q: Do not to load the default resource file.
-:-l *file*, -load-vernac-source *file*: Load and execute the |Coq|
+:-l *file*, -load-vernac-source *file*: Load and execute the Coq
script from *file.v*.
:-lv *file*, -load-vernac-source-verbose *file*: Load and execute the
- |Coq| script from *file.v*. Write its contents to the standard output as
+ Coq script from *file.v*. Write its contents to the standard output as
it is executed.
-:-load-vernac-object *qualid*: Load |Coq| compiled library :n:`@qualid`. This
+:-load-vernac-object *qualid*: Load Coq compiled library :n:`@qualid`. This
is equivalent to running :cmd:`Require` :n:`@qualid`.
.. _interleave-command-line:
@@ -191,27 +191,27 @@ and ``coqtop``, unless stated otherwise:
:cmd:`Unset` commands will be executed in the order specified on
the command-line.
-:-rfrom *dirpath* *qualid*: Load |Coq| compiled library :n:`@qualid`.
+:-rfrom *dirpath* *qualid*: Load Coq compiled library :n:`@qualid`.
This is equivalent to running :cmd:`From <From … Require>`
:n:`@dirpath` :cmd:`Require <From … Require>` :n:`@qualid`.
See the :ref:`note above <interleave-command-line>` regarding the order
of command-line options.
-:-ri *qualid*, -require-import *qualid*: Load |Coq| compiled library :n:`@qualid` and import it.
+:-ri *qualid*, -require-import *qualid*: Load Coq compiled library :n:`@qualid` and import it.
This is equivalent to running :cmd:`Require Import` :n:`@qualid`.
See the :ref:`note above <interleave-command-line>` regarding the order
of command-line options.
-:-re *qualid*, -require-export *qualid*: Load |Coq| compiled library :n:`@qualid` and transitively import it.
+:-re *qualid*, -require-export *qualid*: Load Coq compiled library :n:`@qualid` and transitively import it.
This is equivalent to running :cmd:`Require Export` :n:`@qualid`.
See the :ref:`note above <interleave-command-line>` regarding the order
of command-line options.
:-rifrom *dirpath* *qualid*, -require-import-from *dirpath* *qualid*:
- Load |Coq| compiled library :n:`@qualid` and import it. This is
+ Load Coq compiled library :n:`@qualid` and import it. This is
equivalent to running :cmd:`From <From … Require>` :n:`@dirpath`
:cmd:`Require Import <From … Require>` :n:`@qualid`. See the
:ref:`note above <interleave-command-line>` regarding the order of
command-line options.
:-refrom *dirpath* *qualid*, -require-export-from *dirpath* *qualid*:
- Load |Coq| compiled library :n:`@qualid` and transitively import it.
+ Load Coq compiled library :n:`@qualid` and transitively import it.
This is equivalent to running :cmd:`From <From … Require>`
:n:`@dirpath` :cmd:`Require Export <From … Require>` :n:`@qualid`.
See the :ref:`note above <interleave-command-line>` regarding the
@@ -219,11 +219,11 @@ and ``coqtop``, unless stated otherwise:
:-batch: Exit just after argument parsing. Available for ``coqtop`` only.
:-verbose: Output the content of the input file as it is compiled.
This option is available for ``coqc`` only.
-:-vos: Indicate |Coq| to skip the processing of opaque proofs
+:-vos: Indicate Coq to skip the processing of opaque proofs
(i.e., proofs ending with :cmd:`Qed` or :cmd:`Admitted`), output a ``.vos`` files
instead of a ``.vo`` file, and to load ``.vos`` files instead of ``.vo`` files
when interpreting :cmd:`Require` commands.
-:-vok: Indicate |Coq| to check a file completely, to load ``.vos`` files instead
+:-vok: Indicate Coq to check a file completely, to load ``.vos`` files instead
of ``.vo`` files when interpreting :cmd:`Require` commands, and to output an empty
``.vok`` files upon success instead of writing a ``.vo`` file.
:-w (all|none|w₁,…,wₙ): Configure the display of warnings. This
@@ -241,7 +241,7 @@ and ``coqtop``, unless stated otherwise:
syntax/definitions/notations.
:-emacs, -ide-slave: Start a special toplevel to communicate with a
specific IDE.
-:-impredicative-set: Change the logical theory of |Coq| by declaring the
+:-impredicative-set: Change the logical theory of Coq by declaring the
sort :g:`Set` impredicative.
.. warning::
@@ -249,12 +249,12 @@ and ``coqtop``, unless stated otherwise:
This is known to be inconsistent with some
standard axioms of classical mathematics such as the functional
axiom of choice or the principle of description.
-:-type-in-type: Collapse the universe hierarchy of |Coq|.
+:-type-in-type: Collapse the universe hierarchy of Coq.
.. warning:: This makes the logic inconsistent.
:-mangle-names *ident*: *Experimental.* Do not depend on this option. Replace
- |Coq|'s auto-generated name scheme with names of the form *ident0*, *ident1*,
- etc. Within |Coq|, the :flag:`Mangle Names` flag turns this behavior on,
+ Coq's auto-generated name scheme with names of the form *ident0*, *ident1*,
+ etc. Within Coq, the :flag:`Mangle Names` flag turns this behavior on,
and the :opt:`Mangle Names Prefix` option sets the prefix to use. This feature
is intended to be used as a linter for developments that want to be robust to
changes in the auto-generated name scheme. The options are provided to
@@ -264,7 +264,7 @@ and ``coqtop``, unless stated otherwise:
type of the option. For flags :n:`@setting_name` is equivalent to
:n:`@setting_name=true`. For instance ``-set "Universe Polymorphism"``
will enable :flag:`Universe Polymorphism`. Note that the quotes are
- shell syntax, |Coq| does not see them.
+ shell syntax, Coq does not see them.
See the :ref:`note above <interleave-command-line>` regarding the order
of command-line options.
:-unset *string*: As ``-set`` but used to disable options and flags.
@@ -285,16 +285,16 @@ and ``coqtop``, unless stated otherwise:
:-no-glob: Disable the dumping of references for global names.
:-image *file*: Set the binary image to be used by ``coqc`` to be *file*
instead of the standard one. Not of general use.
-:-bindir *directory*: Set the directory containing |Coq| binaries to be
+:-bindir *directory*: Set the directory containing Coq binaries to be
used by ``coqc``. It is equivalent to doing export COQBIN= *directory*
before launching ``coqc``.
-:-where: Print the location of |Coq|’s standard library and exit.
-:-config: Print the locations of |Coq|’s binaries, dependencies, and
+:-where: Print the location of Coq’s standard library and exit.
+:-config: Print the locations of Coq’s binaries, dependencies, and
libraries, then exit.
:-filteropts: Print the list of command line arguments that `coqtop` has
recognized as options and exit.
-:-v: Print |Coq|’s version and exit.
-:-list-tags: Print the highlight tags known by |Coq| as well as their
+:-v: Print Coq’s version and exit.
+:-list-tags: Print the highlight tags known by Coq as well as their
currently associated color and exit.
:-h, --help: Print a short usage and exit.
@@ -304,7 +304,7 @@ and ``coqtop``, unless stated otherwise:
Compiled interfaces (produced using ``-vos``)
----------------------------------------------
-Compiled interfaces help saving time while developing |Coq| formalizations,
+Compiled interfaces help saving time while developing Coq formalizations,
by compiling the formal statements exported by a library independently of
the proofs that it contains.
@@ -401,7 +401,7 @@ within a section.
.. warn:: You should use the “Proof using [...].” syntax instead of “Proof.” to enable skipping this proof which is located inside a section. Give as argument to “Proof using” the list of section variables that are not needed to typecheck the statement but that are required by the proof.
- If |Coq| is invoked using the ``-vos`` option, whenever it finds the
+ If Coq is invoked using the ``-vos`` option, whenever it finds the
command ``Proof.`` inside a section, it will compile the proof, that is,
refuse to skip it, and it will raise a warning. To disable the warning, one
may pass the flag ``-w -proof-without-using-in-section``.
@@ -412,7 +412,7 @@ When compiling a file ``foo.v`` using ``coqc`` in the standard way (i.e., withou
``-vos`` nor ``-vok``), an empty file ``foo.vos`` and an empty file ``foo.vok``
are created in addition to the regular output file ``foo.vo``.
If ``coqc`` is subsequently invoked on some other file ``bar.v`` using option
-``-vos`` or ``-vok``, and that ``bar.v`` requires ``foo.v``, if |Coq| finds an
+``-vos`` or ``-vok``, and that ``bar.v`` requires ``foo.v``, if Coq finds an
empty file ``foo.vos``, then it will load ``foo.vo`` instead of ``foo.vos``.
The purpose of this feature is to allow users to benefit from the ``-vos``
@@ -473,7 +473,7 @@ set of reflexive transitive dependencies of set :math:`S`. Then:
context without type checking. Basic integrity checks (checksums) are
nonetheless performed.
-As a rule of thumb, -admit can be used to tell |Coq| that some libraries
+As a rule of thumb, -admit can be used to tell Coq that some libraries
have already been checked. So ``coqchk A B`` can be split in ``coqchk A`` &&
``coqchk B -admit A`` without type checking any definition twice. Of
course, the latter is slightly slower since it makes more disk access.
diff --git a/doc/sphinx/practical-tools/coqide.rst b/doc/sphinx/practical-tools/coqide.rst
index 64b433115c..c239797cc2 100644
--- a/doc/sphinx/practical-tools/coqide.rst
+++ b/doc/sphinx/practical-tools/coqide.rst
@@ -2,28 +2,28 @@
.. _coqintegrateddevelopmentenvironment:
-|Coq| Integrated Development Environment
+Coq Integrated Development Environment
========================================
-The |Coq| Integrated Development Environment is a graphical tool, to be
+The Coq Integrated Development Environment is a graphical tool, to be
used as a user-friendly replacement to `coqtop`. Its main purpose is to
-allow the user to navigate forward and backward into a |Coq| vernacular
+allow the user to navigate forward and backward into a Coq vernacular
file, executing corresponding commands or undoing them respectively.
-|CoqIDE| is run by typing the command `coqide` on the command line.
+CoqIDE is run by typing the command `coqide` on the command line.
Without argument, the main screen is displayed with an “unnamed
buffer”, and with a filename as argument, another buffer displaying
the contents of that file. Additionally, `coqide` accepts the same
options as `coqtop`, given in :ref:`thecoqcommands`, the ones having obviously
-no meaning for |CoqIDE| being ignored.
+no meaning for CoqIDE being ignored.
.. _coqide_mainscreen:
.. image:: ../_static/coqide.png
- :alt: |CoqIDE| main screen
+ :alt: CoqIDE main screen
-A sample |CoqIDE| main screen, while navigating into a file `Fermat.v`,
-is shown in the figure :ref:`|CoqIDE| main screen <coqide_mainscreen>`.
+A sample CoqIDE main screen, while navigating into a file `Fermat.v`,
+is shown in the figure :ref:`CoqIDE main screen <coqide_mainscreen>`.
At the top is a menu bar, and a tool bar
below it. The large window on the left is displaying the various
*script buffers*. The upper right window is the *goal window*, where
@@ -39,15 +39,15 @@ The *File* menu allows you to open files or create some, save them,
print or export them into various formats. Among all these buffers,
there is always one which is the current *running buffer*, whose name
is displayed on a background in the *processed* color (green by default), which
-is the one where |Coq| commands are currently executed.
+is the one where Coq commands are currently executed.
Buffers may be edited as in any text editor, and classical basic
editing commands (Copy/Paste, …) are available in the *Edit* menu.
-|CoqIDE| offers only basic editing commands, so if you need more complex
+CoqIDE offers only basic editing commands, so if you need more complex
editing commands, you may launch your favorite text editor on the
current buffer, using the *Edit/External Editor* menu.
-Interactive navigation into |Coq| scripts
+Interactive navigation into Coq scripts
--------------------------------------------
The running buffer is the one where navigation takes place. The toolbar offers
@@ -58,7 +58,7 @@ processed color. If that command fails, the error message is displayed in the
message window, and the location of the error is emphasized by an underline in
the error foreground color (red by default).
-In the figure :ref:`|CoqIDE| main screen <coqide_mainscreen>`,
+In the figure :ref:`CoqIDE main screen <coqide_mainscreen>`,
the running buffer is `Fermat.v`, all commands until
the ``Theorem`` have been already executed, and the user tried to go
forward executing ``Induction n``. That command failed because no such
@@ -74,7 +74,7 @@ and use the goto button. Unlike with `coqtop`, you should never use
There are two additional buttons for navigation within the running buffer. The
"down" button with a line goes directly to the end; the "up" button with a line
goes back to the beginning. The handling of errors when using the go-to-the-end
-button depends on whether |Coq| is running in asynchronous mode or not (see
+button depends on whether Coq is running in asynchronous mode or not (see
Chapter :ref:`asynchronousandparallelproofprocessing`). If it is not running in that mode, execution
stops as soon as an error is found. Otherwise, execution continues, and the
error is marked with an underline in the error foreground color, with a
@@ -86,12 +86,12 @@ If you ever try to execute a command that runs for a long time
and would like to abort it before it terminates, you may
use the interrupt button (the white cross on a red circle).
-There are other buttons on the |CoqIDE| toolbar: a button to save the running
+There are other buttons on the CoqIDE toolbar: a button to save the running
buffer; a button to close the current buffer (an "X"); buttons to switch among
buffers (left and right arrows); an "information" button; and a "gears" button.
-The "gears" button submits proof terms to the |Coq| kernel for type checking.
-When |Coq| uses asynchronous processing (see Chapter :ref:`asynchronousandparallelproofprocessing`),
+The "gears" button submits proof terms to the Coq kernel for type checking.
+When Coq uses asynchronous processing (see Chapter :ref:`asynchronousandparallelproofprocessing`),
proofs may have been completed without kernel-checking of generated proof terms.
The presence of unchecked proof terms is indicated by ``Qed`` statements that
have a subdued *being-processed* color (light blue by default), rather than the
@@ -114,11 +114,11 @@ Queries
------------
.. image:: ../_static/coqide-queries.png
- :alt: |CoqIDE| queries
+ :alt: CoqIDE queries
We call *query* any vernacular command that does not change the current state,
such as ``Check``, ``Search``, etc. To run such commands interactively, without
-writing them in scripts, |CoqIDE| offers a *query pane*. The query pane can be
+writing them in scripts, CoqIDE offers a *query pane*. The query pane can be
displayed on demand by using the ``View`` menu, or using the shortcut ``F1``.
Queries can also be performed by selecting a particular phrase, then choosing an
item from the ``Queries`` menu. The response then appears in the message window.
@@ -148,12 +148,12 @@ The first section is for selecting the text font used for scripts,
goal and message windows.
The second and third sections are for controlling colors and style of
-the three main buffers. A predefined |Coq| highlighting style as well
+the three main buffers. A predefined Coq highlighting style as well
as standard |GtkSourceView| styles are available. Other styles can be
added e.g. in ``$HOME/.local/share/gtksourceview-3.0/styles/`` (see
the general documentation about |GtkSourceView| for the various
possibilities). Note that the style of the rest of graphical part of
-|CoqIDE| is not under the control of |GtkSourceView| but of GTK+ and
+CoqIDE is not under the control of |GtkSourceView| but of GTK+ and
governed by files such as ``settings.ini`` and ``gtk.css`` in
``$XDG_CONFIG_HOME/gtk-3.0`` or files in
``$HOME/.themes/NameOfTheme/gtk-3.0``, as well as the environment
@@ -169,7 +169,7 @@ The next section is devoted to file management: you may configure
automatic saving of files, by periodically saving the contents into
files named `#f#` for each opened file `f`. You may also activate the
*revert* feature: in case a opened file is modified on the disk by a
-third party, |CoqIDE| may read it again for you. Note that in the case
+third party, CoqIDE may read it again for you. Note that in the case
you edited that same file, you will be prompted to choose to either
discard your changes or not. The File charset encoding choice is
described below in :ref:`character-encoding-saved-files`.
@@ -196,9 +196,9 @@ still edit this configuration file by hand, but this is more involved.
Using Unicode symbols
--------------------------
-|CoqIDE| is based on GTK+ and inherits from it support for Unicode in
+CoqIDE is based on GTK+ and inherits from it support for Unicode in
its text windows. Consequently a large set of symbols is available for
-notations. Furthermore, |CoqIDE| conveniently provides a simple way to
+notations. Furthermore, CoqIDE conveniently provides a simple way to
input Unicode characters.
@@ -219,9 +219,9 @@ mathematical symbols ∀ and ∃, you may define:
: type_scope.
There exists a small set of such notations already defined, in the
-file `utf8.v` of |Coq| library, so you may enable them just by
-``Require Import Unicode.Utf8`` inside |CoqIDE|, or equivalently,
-by starting |CoqIDE| with ``coqide -l utf8``.
+file `utf8.v` of Coq library, so you may enable them just by
+``Require Import Unicode.Utf8`` inside CoqIDE, or equivalently,
+by starting CoqIDE with ``coqide -l utf8``.
However, there are some issues when using such Unicode symbols: you of
course need to use a character font which supports them. In the Fonts
@@ -237,7 +237,7 @@ use antialiased fonts or not, by setting the environment variable
Bindings for input of Unicode symbols
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-|CoqIDE| supports a builtin mechanism to input non-ASCII symbols.
+CoqIDE supports a builtin mechanism to input non-ASCII symbols.
For example, to input ``π``, it suffices to type ``\pi`` then press the
combination of key ``Shift+Space`` (default key binding). Often, it
suffices to type a prefix of the latex token, e.g. typing ``\p``
@@ -255,7 +255,7 @@ Custom bindings may be added, as explained further on.
.. note::
It remains possible to input non-ASCII symbols using system-wide
- approaches independent of |CoqIDE|.
+ approaches independent of CoqIDE.
Adding custom bindings
@@ -286,7 +286,7 @@ Similarly, the above settings ensure than ``\l`` resolves to ``\le``,
and that ``\la`` resolves to ``\lambda``.
It can be useful to work with per-project binding files. For this purpose
-|CoqIDE| accepts a command line argument of the form
+CoqIDE accepts a command line argument of the form
``-unicode-bindings file1,file2,...,fileN``.
Each of the file tokens provided may consists of one of:
@@ -320,7 +320,7 @@ related to the way files are saved.
If you have no need to exchange files with non UTF-8 aware
applications, it is better to choose the UTF-8 encoding, since it
guarantees that your files will be read again without problems. (This
-is because when |CoqIDE| reads a file, it tries to automatically detect
+is because when CoqIDE reads a file, it tries to automatically detect
its character encoding.)
If you choose something else than UTF-8, then missing characters will
diff --git a/doc/sphinx/practical-tools/utilities.rst b/doc/sphinx/practical-tools/utilities.rst
index c3286199e8..ec3689bbbe 100644
--- a/doc/sphinx/practical-tools/utilities.rst
+++ b/doc/sphinx/practical-tools/utilities.rst
@@ -8,7 +8,7 @@ The distribution provides utilities to simplify some tedious works
beside proof development, tactics writing or documentation.
-Using |Coq| as a library
+Using Coq as a library
------------------------
In previous versions, ``coqmktop`` was used to build custom
@@ -34,21 +34,21 @@ For example, to statically link |Ltac|, you can just do:
and similarly for other plugins.
-Building a |Coq| project
+Building a Coq project
------------------------
-As of today it is possible to build |Coq| projects using two tools:
+As of today it is possible to build Coq projects using two tools:
-- coq_makefile, which is distributed by |Coq| and is based on generating a makefile,
-- Dune, the standard |OCaml| build tool, which, since version 1.9, supports building |Coq| libraries.
+- coq_makefile, which is distributed by Coq and is based on generating a makefile,
+- Dune, the standard OCaml build tool, which, since version 1.9, supports building Coq libraries.
.. _coq_makefile:
-Building a |Coq| project with coq_makefile
+Building a Coq project with coq_makefile
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The majority of |Coq| projects are very similar: a collection of ``.v``
-files and eventually some ``.ml`` ones (a |Coq| plugin). The main piece of
+The majority of Coq projects are very similar: a collection of ``.v``
+files and eventually some ``.ml`` ones (a Coq plugin). The main piece of
metadata needed in order to build the project are the command line
options to ``coqc`` (e.g. ``-R``, ``Q``, ``-I``, see :ref:`command
line options <command-line-options>`). Collecting the list of files
@@ -74,11 +74,11 @@ to literally pass an argument ``foo`` to ``coqc``: in the
example, this allows to pass the two-word option ``-w all`` (see
:ref:`command line options <command-line-options>`).
-|CoqIDE|, Proof-General and VSCoq all
-understand ``_CoqProject`` files and can be used to invoke |Coq| with the desired options.
+CoqIDE, Proof-General and VSCoq all
+understand ``_CoqProject`` files and can be used to invoke Coq with the desired options.
The ``coq_makefile`` utility can be used to set up a build infrastructure
-for the |Coq| project based on makefiles. The recommended way of
+for the Coq project based on makefiles. The recommended way of
invoking ``coq_makefile`` is the following one:
::
@@ -91,14 +91,14 @@ Such command generates the following files:
CoqMakefile
is a makefile for ``GNU Make`` with targets to build the project
(e.g. generate .vo or .html files from .v or compile .ml* files)
- and install it in the ``user-contrib`` directory where the |Coq|
+ and install it in the ``user-contrib`` directory where the Coq
library is installed. Run ``make`` with the ``-f CoqMakefile``
option to use ``CoqMakefile``.
CoqMakefile.conf
contains make variables assignments that reflect
the contents of the ``_CoqProject`` file as well as the path relevant to
- |Coq|.
+ Coq.
An optional file ``CoqMakefile.local`` can be provided by the user in order to
@@ -111,11 +111,11 @@ The extensions of the files listed in ``_CoqProject`` is used in order to
decide how to build them. In particular:
-+ |Coq| files must use the ``.v`` extension
-+ |OCaml| files must use the ``.ml`` or ``.mli`` extension
-+ |OCaml| files that require pre processing for syntax
++ Coq files must use the ``.v`` extension
++ OCaml files must use the ``.ml`` or ``.mli`` extension
++ OCaml files that require pre processing for syntax
extensions (like ``VERNAC EXTEND``) must use the ``.mlg`` extension
-+ In order to generate a plugin one has to list all |OCaml|
++ In order to generate a plugin one has to list all OCaml
modules (i.e. ``Baz`` for ``baz.ml``) in a ``.mlpack`` file (or ``.mllib``
file).
@@ -142,23 +142,23 @@ Here we describe only few of them.
:CAMLPKGS:
can be used to specify third party findlib packages, and is
- passed to the |OCaml| compiler on building or linking of modules. Eg:
+ passed to the OCaml compiler on building or linking of modules. Eg:
``-package yojson``.
:CAMLFLAGS:
- can be used to specify additional flags to the |OCaml|
+ can be used to specify additional flags to the OCaml
compiler, like ``-bin-annot`` or ``-w``....
:OCAMLWARN:
it contains a default of ``-warn-error +a-3``, useful to modify
this setting; beware this is not recommended for projects in
- |Coq|'s CI.
+ Coq's CI.
:COQC, COQDEP, COQDOC:
can be set in order to use alternative binaries
(e.g. wrappers)
:COQ_SRC_SUBDIRS:
can be extended by including other paths in which ``*.cm*`` files
are searched. For example ``COQ_SRC_SUBDIRS+=user-contrib/Unicoq``
- lets you build a plugin containing |OCaml| code that depends on the
- |OCaml| code of ``Unicoq``
+ lets you build a plugin containing OCaml code that depends on the
+ OCaml code of ``Unicoq``
:COQFLAGS:
override the flags passed to ``coqc``. By default ``-q``.
:COQEXTRAFLAGS:
@@ -172,7 +172,7 @@ Here we describe only few of them.
:COQDOCEXTRAFLAGS:
extend the flags passed to ``coqdoc``
:COQLIBINSTALL, COQDOCINSTALL:
- specify where the |Coq| libraries and documentation will be installed.
+ specify where the Coq libraries and documentation will be installed.
By default a combination of ``$(DESTDIR)`` (if defined) with
``$(COQLIB)/user-contrib`` and ``$(DOCDIR)/user-contrib``.
@@ -524,7 +524,7 @@ Precompiling for ``native_compute``
+++++++++++++++++++++++++++++++++++
To compile files for ``native_compute``, one can use the
-``-native-compiler yes`` option of |Coq|, for instance by putting the
+``-native-compiler yes`` option of Coq, for instance by putting the
following in a :ref:`coqmakefilelocal` file:
::
@@ -555,27 +555,27 @@ of installing the extra ``.coq-native`` directories.
This requires all dependencies to be themselves compiled with
``-native-compiler yes``.
-Building a |Coq| project with Dune
+Building a Coq project with Dune
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note::
- Dune's |Coq| support is still experimental; we strongly recommend
+ Dune's Coq support is still experimental; we strongly recommend
using Dune 2.3 or later.
.. note::
- The canonical documentation for the |Coq| Dune extension is
+ The canonical documentation for the Coq Dune extension is
maintained upstream; please refer to the `Dune manual
<https://dune.readthedocs.io/>`_ for up-to-date information. This
documentation is up to date for Dune 2.3.
-Building a |Coq| project with Dune requires setting up a Dune project
+Building a Coq project with Dune requires setting up a Dune project
for your files. This involves adding a ``dune-project`` and
``pkg.opam`` file to the root (``pkg.opam`` can be empty or generated
by Dune itself), and then providing ``dune`` files in the directories
your ``.v`` files are placed. For the experimental version "0.1" of
-the |Coq| Dune language, |Coq| library stanzas look like:
+the Coq Dune language, Coq library stanzas look like:
.. code:: scheme
@@ -592,12 +592,12 @@ the library under ``<module_prefix>``. If you declare an
``<opam_package>``, an ``.install`` file for the library will be
generated; the optional ``(modules <ordered_set_lang>)`` field allows
you to filter the list of modules, and ``(libraries
-<ocaml_libraries>)`` allows the |Coq| theory depend on ML plugins. For
-the moment, Dune relies on |Coq|'s standard mechanisms (such as
-``COQPATH``) to locate installed |Coq| libraries.
+<ocaml_libraries>)`` allows the Coq theory depend on ML plugins. For
+the moment, Dune relies on Coq's standard mechanisms (such as
+``COQPATH``) to locate installed Coq libraries.
By default Dune will skip ``.v`` files present in subdirectories. In
-order to enable the usual recursive organization of |Coq| projects add
+order to enable the usual recursive organization of Coq projects add
.. code:: scheme
@@ -611,7 +611,7 @@ of your project.
.. example::
- A typical stanza for a |Coq| plugin is split into two parts. An |OCaml| build directive, which is standard Dune:
+ A typical stanza for a Coq plugin is split into two parts. An OCaml build directive, which is standard Dune:
.. code:: scheme
@@ -623,7 +623,7 @@ of your project.
(coq.pp (modules g_equations))
- And a |Coq|-specific part that depends on it via the ``libraries`` field:
+ And a Coq-specific part that depends on it via the ``libraries`` field:
.. code:: scheme
@@ -642,37 +642,37 @@ Computing Module dependencies
-----------------------------
In order to compute module dependencies (to be used by ``make`` or
-``dune``), |Coq| provides the ``coqdep`` tool.
+``dune``), Coq provides the ``coqdep`` tool.
-``coqdep`` computes inter-module dependencies for |Coq|
+``coqdep`` computes inter-module dependencies for Coq
programs, and prints the dependencies on the standard output in a
format readable by make. When a directory is given as argument, it is
recursively looked at.
-Dependencies of |Coq| modules are computed by looking at ``Require``
+Dependencies of Coq modules are computed by looking at ``Require``
commands (``Require``, ``Require Export``, ``Require Import``), but also at the
command ``Declare ML Module``.
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.
+dependencies among the files part of a Coq project.
-Embedded |Coq| phrases inside |Latex| documents
+Embedded Coq phrases inside |Latex| documents
-----------------------------------------------
When writing documentation about a proof development, one may want
-to insert |Coq| phrases inside a |Latex| document, possibly together
+to insert Coq phrases inside a |Latex| document, possibly together
with the corresponding answers of the system. We provide a mechanical
-way to process such |Coq| phrases embedded in |Latex| files: the ``coq-tex``
-filter. This filter extracts |Coq| phrases embedded in |Latex| files,
+way to process such Coq phrases embedded in |Latex| files: the ``coq-tex``
+filter. This filter extracts Coq phrases embedded in |Latex| files,
evaluates them, and insert the outcome of the evaluation after each
phrase.
-Starting with a file ``file.tex`` containing |Coq| phrases, the ``coq-tex``
-filter produces a file named ``file.v.tex`` with the |Coq| outcome.
+Starting with a file ``file.tex`` containing Coq phrases, the ``coq-tex``
+filter produces a file named ``file.v.tex`` with the Coq outcome.
-There are options to produce the |Coq| parts in smaller font, italic,
+There are options to produce the Coq parts in smaller font, italic,
between horizontal rules, etc. See the man page of ``coq-tex`` for more
details.
diff --git a/doc/sphinx/proof-engine/ltac.rst b/doc/sphinx/proof-engine/ltac.rst
index 8663ac646b..6464f085b8 100644
--- a/doc/sphinx/proof-engine/ltac.rst
+++ b/doc/sphinx/proof-engine/ltac.rst
@@ -8,7 +8,7 @@ This chapter documents the tactic language |Ltac|.
We start by giving the syntax followed by the informal
semantics. To learn more about the language and
especially about its foundations, please refer to :cite:`Del00`.
-(Note the examples in the paper won't work as-is; |Coq| has evolved
+(Note the examples in the paper won't work as-is; Coq has evolved
since the paper was written.)
.. example:: Basic tactic macros
@@ -41,7 +41,7 @@ higher precedence than `+`. Usually `a/b/c` is given the :gdef:`left associativ
interpretation `(a/b)/c` rather than the :gdef:`right associative` interpretation
`a/(b/c)`.
-In |Coq|, the expression :n:`try repeat @tactic__1 || @tactic__2; @tactic__3; @tactic__4`
+In Coq, the expression :n:`try repeat @tactic__1 || @tactic__2; @tactic__3; @tactic__4`
is interpreted as :n:`(try (repeat (@tactic__1 || @tactic__2)); @tactic__3); @tactic__4`
because `||` is part of :token:`ltac_expr2`, which has higher precedence than
:tacn:`try` and :tacn:`repeat` (at the level of :token:`ltac_expr3`), which
@@ -60,7 +60,7 @@ The constructs in :token:`ltac_expr` are :term:`left associative`.
ltac_expr3 ::= @l3_tactic
| @ltac_expr2
ltac_expr2 ::= @ltac_expr1 + {| @ltac_expr2 | @binder_tactic }
- | @ltac_expr1 || {| @ltac_expr2 | @binder_tactic }
+ | @ltac_expr1 %|| {| @ltac_expr2 | @binder_tactic }
| @l2_tactic
| @ltac_expr1
ltac_expr1 ::= @tactic_value
@@ -729,7 +729,7 @@ First tactic to make progress: ||
Yet another way of branching without backtracking is the following
structure:
-.. tacn:: @ltac_expr1 || {| @ltac_expr2 | @binder_tactic }
+.. tacn:: @ltac_expr1 %|| {| @ltac_expr2 | @binder_tactic }
:name: || (first tactic making progress)
:n:`@ltac_expr1 || @ltac_expr2` is
@@ -784,7 +784,7 @@ single success:
Checking for a single success: exactly_once
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-|Coq| provides an experimental way to check that a tactic has *exactly
+Coq provides an experimental way to check that a tactic has *exactly
one* success:
.. tacn:: exactly_once @ltac_expr3
@@ -813,7 +813,7 @@ one* success:
Checking for failure: assert_fails
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-|Coq| defines an |Ltac| tactic in `Init.Tactics` to check that a tactic *fails*:
+Coq defines an |Ltac| tactic in `Init.Tactics` to check that a tactic *fails*:
.. tacn:: assert_fails @ltac_expr3
:name: assert_fails
@@ -859,7 +859,7 @@ Checking for failure: assert_fails
Checking for success: assert_succeeds
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-|Coq| defines an |Ltac| tactic in `Init.Tactics` to check that a tactic has *at least one*
+Coq defines an |Ltac| tactic in `Init.Tactics` to check that a tactic has *at least one*
success:
.. tacn:: assert_succeeds @ltac_expr3
@@ -905,7 +905,7 @@ Failing
See the example for a comparison of the two constructs.
- Note that if |Coq| terms have to be
+ Note that if Coq terms have to be
printed as part of the failure, term construction always forces the
tactic into the goals, meaning that if there are no goals when it is
evaluated, a tactic call like :tacn:`let` :n:`x := H in` :tacn:`fail` `0 x` will succeed.
@@ -990,7 +990,7 @@ amount of time:
timeout with some other tacticals. This tactical is hence proposed only
for convenience during debugging or other development phases, we strongly
advise you to not leave any timeout in final scripts. Note also that
- this tactical isn’t available on the native Windows port of |Coq|.
+ this tactical isn’t available on the native Windows port of Coq.
Timing a tactic
~~~~~~~~~~~~~~~
@@ -1353,8 +1353,8 @@ Pattern matching on goals and hypotheses: match goal
.. insertprodn goal_pattern match_hyp
.. prodn::
- goal_pattern ::= {*, @match_hyp } |- @match_pattern
- | [ {*, @match_hyp } |- @match_pattern ]
+ goal_pattern ::= {*, @match_hyp } %|- @match_pattern
+ | [ {*, @match_hyp } %|- @match_pattern ]
| _
match_hyp ::= @name : @match_pattern
| @name := @match_pattern
@@ -1523,7 +1523,7 @@ produce subgoals but generates a term to be used in tactic expressions:
Generating fresh hypothesis names
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Tactics sometimes need to generate new names for hypothesis. Letting |Coq|
+Tactics sometimes need to generate new names for hypothesis. Letting Coq
choose a name with the intro tactic is not so good since it is
very awkward to retrieve that name. The following
expression returns an identifier:
@@ -1730,6 +1730,8 @@ Defining |Ltac| symbols
|Ltac| toplevel definitions are made as follows:
+.. index:: ::=
+
.. cmd:: Ltac @tacdef_body {* with @tacdef_body }
:name: Ltac
@@ -1754,10 +1756,15 @@ Defining |Ltac| symbols
Defines a user-defined symbol, but gives an error if the symbol has already
been defined.
-.. todo apparent inconsistency: "Ltac intros := idtac" seems like it redefines/hides an existing tactic,
- but in fact it creates a tactic which can only be called by it's qualified name. This is true in general
- of tactic notations. The only way to overwrite most primitive tactics, and any user-defined tactic
- notation, is with another tactic notation.
+ .. todo apparent inconsistency:
+
+ "Ltac intros := idtac" seems like it redefines/hides an
+ existing tactic, but in fact it creates a tactic which can
+ only be called by its qualified name. This is true in
+ general of tactic notations. The only way to overwrite most
+ primitive tactics, and any user-defined tactic notation, is
+ with another tactic notation.
+
.. exn:: There is already an Ltac named @qualid
:undocumented:
@@ -1767,7 +1774,8 @@ Defining |Ltac| symbols
do not count as user-defined tactics for `::=`. If :attr:`local` is not
specified, the redefinition applies across module boundaries.
- .. exn: There is no Ltac named @qualid
+ .. exn:: There is no Ltac named @qualid
+ :undocumented:
:n:`{* with @tacdef_body }`
Permits definition of mutually recursive tactics.
@@ -1885,7 +1893,7 @@ Proving that a list is a permutation of a second list
From Section :ref:`ltac-syntax` we know that Ltac has a primitive
notion of integers, but they are only used as arguments for
primitive tactics and we cannot make computations with them. Thus,
- instead, we use |Coq|'s natural number type :g:`nat`.
+ instead, we use Coq's natural number type :g:`nat`.
.. coqtop:: in
diff --git a/doc/sphinx/proof-engine/ltac2.rst b/doc/sphinx/proof-engine/ltac2.rst
index 64fc1133f0..a46f4fb894 100644
--- a/doc/sphinx/proof-engine/ltac2.rst
+++ b/doc/sphinx/proof-engine/ltac2.rst
@@ -4,7 +4,7 @@ Ltac2
=====
The |Ltac| tactic language is probably one of the ingredients of the success of
-|Coq|, yet it is at the same time its Achilles' heel. Indeed, |Ltac|:
+Coq, yet it is at the same time its Achilles' heel. Indeed, |Ltac|:
- has often unclear semantics
- is very non-uniform due to organic growth
@@ -30,7 +30,7 @@ as Ltac1.
Current limitations include:
- There are a number of tactics that are not yet supported in Ltac2 because
- the interface |OCaml| and/or Ltac2 notations haven't been written. See
+ the interface OCaml and/or Ltac2 notations haven't been written. See
:ref:`defining_tactics`.
- Missing usability features such as:
@@ -38,7 +38,6 @@ Current limitations include:
- Printing functions are limited and awkward to use. Only a few data types are
printable.
- Deep pattern matching and matching on tuples don't work.
- - If statements on Ltac2 boolean values
- A convenient way to build terms with casts through the low-level API. Because the
cast type is opaque, building terms with casts currently requires an awkward construction like the
following, which also incurs extra overhead to repeat typechecking for each
@@ -90,7 +89,7 @@ In particular, Ltac2 is:
* together with the Hindley-Milner type system
- a language featuring meta-programming facilities for the manipulation of
- |Coq|-side terms
+ Coq-side terms
- a language featuring notation facilities to help write palatable scripts
We describe these in more detail in the remainder of this document.
@@ -108,14 +107,14 @@ that ML constitutes a sweet spot in PL design, as it is relatively expressive
while not being either too lax (unlike dynamic typing) nor too strict
(unlike, say, dependent types).
-The main goal of Ltac2 is to serve as a meta-language for |Coq|. As such, it
+The main goal of Ltac2 is to serve as a meta-language for Coq. As such, it
naturally fits in the ML lineage, just as the historical ML was designed as
the tactic language for the LCF prover. It can also be seen as a general-purpose
-language, by simply forgetting about the |Coq|-specific features.
+language, by simply forgetting about the Coq-specific features.
Sticking to a standard ML type system can be considered somewhat weak for a
-meta-language designed to manipulate |Coq| terms. In particular, there is no
-way to statically guarantee that a |Coq| term resulting from an Ltac2
+meta-language designed to manipulate Coq terms. In particular, there is no
+way to statically guarantee that a Coq term resulting from an Ltac2
computation will be well-typed. This is actually a design choice, motivated
by backward compatibility with Ltac1. Instead, well-typedness is deferred to
dynamic checks, allowing many primitive functions to fail whenever they are
@@ -138,7 +137,7 @@ Type Syntax
~~~~~~~~~~~
At the level of terms, we simply elaborate on Ltac1 syntax, which is quite
-close to |OCaml|. Types follow the simply-typed syntax of |OCaml|.
+close to OCaml. Types follow the simply-typed syntax of OCaml.
.. insertprodn ltac2_type ltac2_typevar
@@ -160,7 +159,7 @@ declarations such as algebraic datatypes and records.
Built-in types include:
-- ``int``, machine integers (size not specified, in practice inherited from |OCaml|)
+- ``int``, machine integers (size not specified, in practice inherited from OCaml)
- ``string``, mutable strings
- ``'a array``, mutable arrays
- ``exn``, exceptions
@@ -201,7 +200,7 @@ One can define new types with the following commands.
:token:`tac2typ_knd` should be in the form :n:`[ {? {? %| } {+| @tac2alg_constructor } } ]`.
Without :n:`{| := | ::= }`
- Defines an abstract type for use representing data from |OCaml|. Not for
+ Defines an abstract type for use representing data from OCaml. Not for
end users.
:n:`with @tac2typ_def`
@@ -227,9 +226,9 @@ One can define new types with the following commands.
.. cmd:: Ltac2 @ external @ident : @ltac2_type := @string @string
:name: Ltac2 external
- Declares abstract terms. Frequently, these declare |OCaml| functions
- defined in |Coq| and give their type information. They can also declare
- data structures from |OCaml|. This command has no use for the end user.
+ Declares abstract terms. Frequently, these declare OCaml functions
+ defined in Coq and give their type information. They can also declare
+ data structures from OCaml. This command has no use for the end user.
APIs
~~~~
@@ -345,12 +344,10 @@ Ltac2 Definitions
.. coqtop:: all
- Ltac2 mutable rec f b := match b with true => 0 | _ => f true end.
- Ltac2 Set f := fun b =>
- match b with true => 1 | _ => f true end.
+ Ltac2 mutable rec f b := if b then 0 else f true.
+ Ltac2 Set f := fun b => if b then 1 else f true.
Ltac2 Eval (f false).
- Ltac2 Set f as oldf := fun b =>
- match b with true => 2 | _ => oldf false end.
+ Ltac2 Set f as oldf := fun b => if b then 2 else oldf false.
Ltac2 Eval (f false).
In the definition, the `f` in the body is resolved statically
@@ -363,7 +360,7 @@ Reduction
~~~~~~~~~
We use the usual ML call-by-value reduction, with an otherwise unspecified
-evaluation order. This is a design choice making it compatible with |OCaml|,
+evaluation order. This is a design choice making it compatible with OCaml,
if ever we implement native compilation. The expected equations are as follows::
(fun x => t) V ≡ t{x := V} (βv)
@@ -407,7 +404,7 @@ standard IO monad as the ambient effectful world, Ltac2 is has a
tactic monad.
Note that the order of evaluation of application is *not* specified and is
-implementation-dependent, as in |OCaml|.
+implementation-dependent, as in OCaml.
We recall that the `Proofview.tactic` monad is essentially a IO monad together
with backtracking state representing the proof state.
@@ -538,7 +535,7 @@ is a proper one or referring to something in the Ltac context.
Likewise, in Ltac1, constr parsing is implicit, so that ``foo 0`` is
not ``foo`` applied to the Ltac integer expression ``0`` (|Ltac| does have a
-notion of integers, though it is not first-class), but rather the |Coq| term
+notion of integers, though it is not first-class), but rather the Coq term
:g:`Datatypes.O`.
The implicit parsing is confusing to users and often gives unexpected results.
@@ -565,16 +562,16 @@ Built-in quotations
| ltac1 : ( @ltac1_expr_in_env )
| ltac1val : ( @ltac1_expr_in_env )
ltac1_expr_in_env ::= @ltac_expr
- | {* @ident } |- @ltac_expr
+ | {* @ident } %|- @ltac_expr
The current implementation recognizes the following built-in quotations:
- ``ident``, which parses identifiers (type ``Init.ident``).
-- ``constr``, which parses |Coq| terms and produces an-evar free term at runtime
+- ``constr``, which parses Coq terms and produces an-evar free term at runtime
(type ``Init.constr``).
-- ``open_constr``, which parses |Coq| terms and produces a term potentially with
+- ``open_constr``, which parses Coq terms and produces a term potentially with
holes at runtime (type ``Init.constr`` as well).
-- ``pattern``, which parses |Coq| patterns and produces a pattern used for term
+- ``pattern``, which parses Coq patterns and produces a pattern used for term
matching (type ``Init.pattern``).
- ``reference`` Qualified names
are globalized at internalization into the corresponding global reference,
@@ -617,7 +614,7 @@ Term Antiquotations
Syntax
++++++
-One can also insert Ltac2 code into |Coq| terms, similar to what is possible in
+One can also insert Ltac2 code into Coq terms, similar to what is possible in
Ltac1.
.. prodn::
@@ -629,7 +626,7 @@ for their side-effects.
Semantics
+++++++++
-A quoted |Coq| term is interpreted in two phases, internalization and
+A quoted Coq term is interpreted in two phases, internalization and
evaluation.
- Internalization is part of the static semantics, that is, it is done at Ltac2
@@ -637,17 +634,17 @@ evaluation.
- Evaluation is part of the dynamic semantics, that is, it is done when
a term gets effectively computed by Ltac2.
-Note that typing of |Coq| terms is a *dynamic* process occurring at Ltac2
+Note that typing of Coq terms is a *dynamic* process occurring at Ltac2
evaluation time, and not at Ltac2 typing time.
Static semantics
****************
-During internalization, |Coq| variables are resolved and antiquotations are
-type checked as Ltac2 terms, effectively producing a ``glob_constr`` in |Coq|
+During internalization, Coq variables are resolved and antiquotations are
+type checked as Ltac2 terms, effectively producing a ``glob_constr`` in Coq
implementation terminology. Note that although it went through the
type checking of **Ltac2**, the resulting term has not been fully computed and
-is potentially ill-typed as a runtime **|Coq|** term.
+is potentially ill-typed as a runtime **Coq** term.
.. example::
@@ -669,7 +666,7 @@ of the corresponding term expression.
let x := '0 in constr:(1 + ltac2:(exact x))
Beware that the typing environment of antiquotations is **not**
-expanded by the |Coq| binders from the term.
+expanded by the Coq binders from the term.
.. example::
@@ -692,17 +689,17 @@ as follows.
`constr:(fun x : nat => ltac2:(exact (hyp @x)))`
-This pattern is so common that we provide dedicated Ltac2 and |Coq| term notations
+This pattern is so common that we provide dedicated Ltac2 and Coq term notations
for it.
- `&x` as an Ltac2 expression expands to `hyp @x`.
-- `&x` as a |Coq| constr expression expands to
+- `&x` as a Coq constr expression expands to
`ltac2:(Control.refine (fun () => hyp @x))`.
-In the special case where Ltac2 antiquotations appear inside a |Coq| term
+In the special case where Ltac2 antiquotations appear inside a Coq term
notation, the notation variables are systematically bound in the body
of the tactic expression with type `Ltac2.Init.preterm`. Such a type represents
-untyped syntactic |Coq| expressions, which can by typed in the
+untyped syntactic Coq expressions, which can by typed in the
current context using the `Ltac2.Constr.pretype` function.
.. example::
@@ -748,9 +745,9 @@ the notation section.
.. prodn:: term += $@lident
-In a |Coq| term, writing :g:`$x` is semantically equivalent to
+In a Coq term, writing :g:`$x` is semantically equivalent to
:g:`ltac2:(Control.refine (fun () => x))`, up to re-typechecking. It allows to
-insert in a concise way an Ltac2 variable of type :n:`constr` into a |Coq| term.
+insert in a concise way an Ltac2 variable of type :n:`constr` into a Coq term.
Match over terms
~~~~~~~~~~~~~~~~
@@ -981,7 +978,7 @@ Match over goals
.. prodn::
goal_match_list ::= {? %| } {+| @gmatch_rule }
gmatch_rule ::= @gmatch_pattern => @ltac2_expr
- gmatch_pattern ::= [ {*, @gmatch_hyp_pattern } |- @ltac2_match_pattern ]
+ gmatch_pattern ::= [ {*, @gmatch_hyp_pattern } %|- @ltac2_match_pattern ]
gmatch_hyp_pattern ::= @name : @ltac2_match_pattern
Matches over goals, similar to Ltac1 :tacn:`match goal`.
@@ -1129,7 +1126,7 @@ Match on values
.. tacn:: match @ltac2_expr5 with {? @ltac2_branches } end
:name: match (Ltac2)
- Matches a value, akin to the |OCaml| `match` construct. By itself, it doesn't cause backtracking
+ Matches a value, akin to the OCaml `match` construct. By itself, it doesn't cause backtracking
as do the `*match*!` and `*match*! goal` constructs.
.. insertprodn ltac2_branches atomic_tac2pat
@@ -1149,6 +1146,13 @@ Match on values
| @tac2pat1 , {*, @tac2pat1 }
| @tac2pat1
+.. tacn:: if @ltac2_expr5__test then @ltac2_expr5__then else @ltac2_expr5__else
+ :name: if-then-else (Ltac2)
+
+ Equivalent to a :tacn:`match <match (Ltac2)>` on a boolean value. If the
+ :n:`@ltac2_expr5__test` evaluates to true, :n:`@ltac2_expr5__then`
+ is evaluated. Otherwise :n:`@ltac2_expr5__else` is evaluated.
+
.. note::
For now, deep pattern matching is not implemented.
@@ -1182,7 +1186,7 @@ Notations
into the right-hand side. The right-hand side is typechecked when the notation is used,
not when it is defined. In the following example, `x` is the formal parameter name and
`constr` is its :ref:`syntactic class<syntactic_classes>`. `print` and `of_constr` are
- functions provided by |Coq| through `Message.v`.
+ functions provided by Coq through `Message.v`.
.. todo "print" doesn't seem to pay attention to "Set Printing All"
@@ -1254,7 +1258,7 @@ Abbreviations
Introduces a special kind of notation, called an abbreviation,
that does not add any parsing rules. It is similar in
- spirit to |Coq| abbreviations (see :cmd:`Notation (abbreviation)`,
+ spirit to Coq abbreviations (see :cmd:`Notation (abbreviation)`,
insofar as its main purpose is to give an
absolute name to a piece of pure syntax, which can be transparently referred to
by this name as if it were a proper definition.
@@ -1281,7 +1285,7 @@ Abbreviations
Defining tactics
~~~~~~~~~~~~~~~~
-Built-in tactics (those defined in |OCaml| code in the |Coq| executable) and Ltac1 tactics,
+Built-in tactics (those defined in OCaml code in the Coq executable) and Ltac1 tactics,
which are defined in `.v` files, must be defined through notations. (Ltac2 tactics can be
defined with :cmd:`Ltac2`.
@@ -1289,7 +1293,7 @@ Notations for many but not all built-in tactics are defined in `Notations.v`, wh
loaded with Ltac2. The Ltac2 syntax for these tactics is often identical or very similar to the
tactic syntax described in other chapters of this documentation. These notations rely on tactic functions
declared in `Std.v`. Functions corresponding to some built-in tactics may not yet be defined in the
-|Coq| executable or declared in `Std.v`. Adding them may require code changes to |Coq| or defining
+Coq executable or declared in `Std.v`. Adding them may require code changes to Coq or defining
workarounds through Ltac1 (described below).
Two examples of syntax differences:
@@ -1321,7 +1325,7 @@ Syntactic classes
~~~~~~~~~~~~~~~~~
The simplest syntactic classes in Ltac2 notations represent individual nonterminals
-from the |Coq| grammar. Only a few selected nonterminals are available as syntactic classes.
+from the Coq grammar. Only a few selected nonterminals are available as syntactic classes.
In addition, there are metasyntactic operations for describing
more complex syntax, such as making an item optional or representing a list of items.
When parsing, each syntactic class expression returns a value that's bound to a name in the
@@ -1598,8 +1602,8 @@ Here is the syntax for the :n:`q_*` nonterminals:
ltac2_clause ::= in @ltac2_in_clause
| at @ltac2_occs_nums
ltac2_in_clause ::= * {? @ltac2_occs }
- | * |- {? @ltac2_concl_occ }
- | {*, @ltac2_hypident_occ } {? |- {? @ltac2_concl_occ } }
+ | * %|- {? @ltac2_concl_occ }
+ | {*, @ltac2_hypident_occ } {? %|- {? @ltac2_concl_occ } }
.. insertprodn q_occurrences ltac2_hypident
@@ -1629,7 +1633,7 @@ Here is the syntax for the :n:`q_*` nonterminals:
.. insertprodn ltac2_oriented_rewriter ltac2_rewriter
.. prodn::
- ltac2_oriented_rewriter ::= {| -> | <- } @ltac2_rewriter
+ ltac2_oriented_rewriter ::= {? {| -> | <- } } @ltac2_rewriter
ltac2_rewriter ::= {? @natural } {? {| ? | ! } } @ltac2_constr_with_bindings
.. insertprodn ltac2_for_each_goal ltac2_goal_tactics
@@ -1795,7 +1799,7 @@ Transition from Ltac1
Owing to the use of a lot of notations, the transition should not be too
difficult. In particular, it should be possible to do it incrementally. That
said, we do *not* guarantee it will be a blissful walk either.
-Hopefully, owing to the fact Ltac2 is typed, the interactive dialogue with |Coq|
+Hopefully, owing to the fact Ltac2 is typed, the interactive dialogue with Coq
will help you.
We list the major changes and the transition strategies hereafter.
diff --git a/doc/sphinx/proof-engine/proof-handling.rst b/doc/sphinx/proof-engine/proof-handling.rst
index b09d6146d8..7f5aacbfdb 100644
--- a/doc/sphinx/proof-engine/proof-handling.rst
+++ b/doc/sphinx/proof-engine/proof-handling.rst
@@ -1,901 +1,5 @@
-.. _proofhandling:
+:orphan:
--------------------
- Proof handling
--------------------
+.. raw:: html
-In |Coq|’s proof editing mode all top-level commands documented in
-Chapter :ref:`vernacularcommands` remain available and the user has access to specialized
-commands dealing with proof development pragmas documented in this
-section. They can also use some other specialized commands called
-*tactics*. They are the very tools allowing the user to deal with
-logical reasoning. They are documented in Chapter :ref:`tactics`.
-
-|Coq| user interfaces usually have a way of marking whether the user has
-switched to proof editing mode. For instance, in coqtop the prompt ``Coq <``   is changed into
-:n:`@ident <`   where :token:`ident` is the declared name of the theorem currently edited.
-
-At each stage of a proof development, one has a list of goals to
-prove. Initially, the list consists only in the theorem itself. After
-having applied some tactics, the list of goals contains the subgoals
-generated by the tactics.
-
-To each subgoal is associated a number of hypotheses called the *local context*
-of the goal. Initially, the local context contains the local variables and
-hypotheses of the current section (see Section :ref:`gallina-assumptions`) and
-the local variables and hypotheses of the theorem statement. It is enriched by
-the use of certain tactics (see e.g. :tacn:`intro`).
-
-When a proof is completed, the message ``Proof completed`` is displayed.
-One can then register this proof as a defined constant in the
-environment. Because there exists a correspondence between proofs and
-terms of λ-calculus, known as the *Curry-Howard isomorphism*
-:cite:`How80,Bar81,Gir89,H89`, |Coq| stores proofs as terms of |Cic|. Those
-terms are called *proof terms*.
-
-
-.. exn:: No focused proof.
-
- |Coq| raises this error message when one attempts to use a proof editing command
- out of the proof editing mode.
-
-.. _proof-editing-mode:
-
-Entering and leaving proof editing mode
----------------------------------------
-
-The proof editing mode is entered by asserting a statement, which typically is
-the assertion of a theorem using an assertion command like :cmd:`Theorem`. The
-list of assertion commands is given in :ref:`Assertions`. The command
-:cmd:`Goal` can also be used.
-
-.. cmd:: Goal @type
-
- This is intended for quick assertion of statements, without knowing in
- advance which name to give to the assertion, typically for quick
- testing of the provability of a statement. If the proof of the
- statement is eventually completed and validated, the statement is then
- bound to the name ``Unnamed_thm`` (or a variant of this name not already
- used for another statement).
-
-.. cmd:: Qed
-
- This command is available in interactive editing proof mode when the
- proof is completed. Then :cmd:`Qed` extracts a proof term from the proof
- script, switches back to |Coq| top-level and attaches the extracted
- proof term to the declared name of the original goal. The name is
- added to the environment as an opaque constant.
-
- .. exn:: Attempt to save an incomplete proof.
- :undocumented:
-
- .. note::
-
- Sometimes an error occurs when building the proof term, because
- tactics do not enforce completely the term construction
- constraints.
-
- The user should also be aware of the fact that since the
- proof term is completely rechecked at this point, one may have to wait
- a while when the proof is large. In some exceptional cases one may
- even incur a memory overflow.
-
-.. cmd:: Save @ident
- :name: Save
-
- Saves a completed proof with the name :token:`ident`, which
- overrides any name provided by the :cmd:`Theorem` command or
- its variants.
-
-.. cmd:: Defined {? @ident }
-
- Similar to :cmd:`Qed` and :cmd:`Save`, except the proof is made *transparent*, which means
- that its content can be explicitly used for type checking and that it can be
- unfolded in conversion tactics (see :ref:`performingcomputations`,
- :cmd:`Opaque`, :cmd:`Transparent`). If :token:`ident` is specified,
- the proof is defined with the given name, which overrides any name
- provided by the :cmd:`Theorem` command or its variants.
-
-.. cmd:: Admitted
-
- This command is available in interactive editing mode to give up
- the current proof and declare the initial goal as an axiom.
-
-.. cmd:: Abort {? {| All | @ident } }
-
- Cancels the current proof development, switching back to
- the previous proof development, or to the |Coq| toplevel if no other
- proof was being edited.
-
- :n:`@ident`
- Aborts editing the proof named :n:`@ident` for use when you have
- nested proofs. See also :flag:`Nested Proofs Allowed`.
-
- :n:`All`
- Aborts all current proofs.
-
- .. exn:: No focused proof (No proof-editing in progress).
- :undocumented:
-
-.. cmd:: Proof @term
- :name: Proof `term`
-
- This command applies in proof editing mode. It is equivalent to
- :n:`exact @term. Qed.`
- That is, you have to give the full proof in one gulp, as a
- proof term (see Section :ref:`applyingtheorems`).
-
- .. warning::
-
- Use of this command is discouraged. In particular, it
- doesn't work in Proof General because it must
- immediately follow the command that opened proof mode, but
- Proof General inserts :cmd:`Unset` :flag:`Silent` before it (see
- `Proof General issue #498
- <https://github.com/ProofGeneral/PG/issues/498>`_).
-
-.. cmd:: Proof
-
- Is a no-op which is useful to delimit the sequence of tactic commands
- which start a proof, after a :cmd:`Theorem` command. It is a good practice to
- use :cmd:`Proof` as an opening parenthesis, closed in the script with a
- closing :cmd:`Qed`.
-
- .. seealso:: :cmd:`Proof with`
-
-.. cmd:: Proof using @section_var_expr {? with @ltac_expr }
-
- .. insertprodn section_var_expr starred_ident_ref
-
- .. prodn::
- section_var_expr ::= {* @starred_ident_ref }
- | {? - } @section_var_expr50
- section_var_expr50 ::= @section_var_expr0 - @section_var_expr0
- | @section_var_expr0 + @section_var_expr0
- | @section_var_expr0
- section_var_expr0 ::= @starred_ident_ref
- | ( @section_var_expr ) {? * }
- starred_ident_ref ::= @ident {? * }
- | Type {? * }
- | All
-
- Opens proof editing mode, declaring the set of
- section variables (see :ref:`gallina-assumptions`) used by the proof.
- At :cmd:`Qed` time, the
- system verifies that the set of section variables used in
- the proof is a subset of the declared one.
-
- The set of declared variables is closed under type dependency. For
- example, if ``T`` is a variable and ``a`` is a variable of type
- ``T``, then the commands ``Proof using a`` and ``Proof using T a``
- are equivalent.
-
- The set of declared variables always includes the variables used by
- the statement. In other words ``Proof using e`` is equivalent to
- ``Proof using Type + e`` for any declaration expression ``e``.
-
- :n:`- @section_var_expr50`
- Use all section variables except those specified by :n:`@section_var_expr50`
-
- :n:`@section_var_expr0 + @section_var_expr0`
- Use section variables from the union of both collections.
- See :ref:`nameaset` to see how to form a named collection.
-
- :n:`@section_var_expr0 - @section_var_expr0`
- Use section variables which are in the first collection but not in the
- second one.
-
- :n:`{? * }`
- Use the transitive closure of the specified collection.
-
- :n:`Type`
- Use only section variables occurring in the statement. Specifying :n:`*`
- uses the forward transitive closure of all the section variables occurring
- in the statement. For example, if the variable ``H`` has type ``p < 5`` then
- ``H`` is in ``p*`` since ``p`` occurs in the type of ``H``.
-
- :n:`All`
- Use all section variables.
-
- .. seealso:: :ref:`tactics-implicit-automation`
-
-Proof using options
-```````````````````
-
-The following options modify the behavior of ``Proof using``.
-
-
-.. opt:: Default Proof Using "@section_var_expr"
- :name: Default Proof Using
-
- Use :n:`@section_var_expr` as the default ``Proof using`` value. E.g. ``Set Default
- Proof Using "a b"`` will complete all ``Proof`` commands not followed by a
- ``using`` part with ``using a b``.
-
-
-.. flag:: Suggest Proof Using
-
- When :cmd:`Qed` is performed, suggest a ``using`` annotation if the user did not
- provide one.
-
-.. _`nameaset`:
-
-Name a set of section hypotheses for ``Proof using``
-````````````````````````````````````````````````````
-
-.. cmd:: Collection @ident := @section_var_expr
-
- This can be used to name a set of section
- hypotheses, with the purpose of making ``Proof using`` annotations more
- compact.
-
- .. example::
-
- Define the collection named ``Some`` containing ``x``, ``y`` and ``z``::
-
- Collection Some := x y z.
-
- Define the collection named ``Fewer`` containing only ``x`` and ``y``::
-
- Collection Fewer := Some - z
-
- Define the collection named ``Many`` containing the set union or set
- difference of ``Fewer`` and ``Some``::
-
- Collection Many := Fewer + Some
- Collection Many := Fewer - Some
-
- Define the collection named ``Many`` containing the set difference of
- ``Fewer`` and the unnamed collection ``x y``::
-
- Collection Many := Fewer - (x y)
-
-
-
-.. cmd:: Existential @natural {? : @type } := @term
-
- This command instantiates an existential variable. :token:`natural` is an index in
- the list of uninstantiated existential variables displayed by :cmd:`Show Existentials`.
-
- This command is intended to be used to instantiate existential
- variables when the proof is completed but some uninstantiated
- existential variables remain. To instantiate existential variables
- during proof edition, you should use the tactic :tacn:`instantiate`.
-
-.. cmd:: Grab Existential Variables
-
- This command can be run when a proof has no more goal to be solved but
- has remaining uninstantiated existential variables. It takes every
- uninstantiated existential variable and turns it into a goal.
-
-Proof modes
-```````````
-
-When entering proof mode through commands such as :cmd:`Goal` and :cmd:`Proof`,
-|Coq| picks by default the |Ltac| mode. Nonetheless, there exist other proof modes
-shipped in the standard |Coq| installation, and furthermore some plugins define
-their own proof modes. The default proof mode used when opening a proof can
-be changed using the following option.
-
-.. opt:: Default Proof Mode @string
-
- Select the proof mode to use when starting a proof. Depending on the proof
- mode, various syntactic constructs are allowed when writing an interactive
- proof. All proof modes support vernacular commands; the proof mode determines
- which tactic language and set of tactic definitions are available. The
- possible option values are:
-
- `"Classic"`
- Activates the |Ltac| language and the tactics with the syntax documented
- in this manual.
- Some tactics are not available until the associated plugin is loaded,
- such as `SSR` or `micromega`.
- This proof mode is set when the :term:`prelude` is loaded.
-
- `"Noedit"`
- No tactic
- language is activated at all. This is the default when the :term:`prelude`
- is not loaded, e.g. through the `-noinit` option for `coqc`.
-
- `"Ltac2"`
- Activates the Ltac2 language and the Ltac2-specific variants of the documented
- tactics.
- This value is only available after :cmd:`Requiring <Require>` Ltac2.
- :cmd:`Importing <Import>` Ltac2 sets this mode.
-
- Some external plugins also define their own proof mode, which can be
- activated with this command.
-
-Navigation in the proof tree
---------------------------------
-
-.. cmd:: Undo {? {? To } @natural }
-
- Cancels the effect of the last :token:`natural` commands or tactics.
- The :n:`To @natural` form goes back to the specified state number.
- If :token:`natural` is not specified, the command goes back one command or tactic.
-
-.. cmd:: Restart
-
- Restores the proof editing process to the original goal.
-
- .. exn:: No focused proof to restart.
- :undocumented:
-
-.. cmd:: Focus {? @natural }
-
- Focuses the attention on the first subgoal to prove or, if :token:`natural` is
- specified, the :token:`natural`\-th. The
- printing of the other subgoals is suspended until the focused subgoal
- is solved or unfocused.
-
- .. deprecated:: 8.8
-
- Prefer the use of bullets or focusing brackets with a goal selector (see below).
-
-.. cmd:: Unfocus
-
- This command restores to focus the goal that were suspended by the
- last :cmd:`Focus` command.
-
- .. deprecated:: 8.8
-
-.. cmd:: Unfocused
-
- Succeeds if the proof is fully unfocused, fails if there are some
- goals out of focus.
-
-.. _curly-braces:
-
-.. index:: {
- }
-
-.. todo: :name: "{"; "}" doesn't work, nor does :name: left curly bracket; right curly bracket,
- hence the verbose names
-
-.. tacn:: {? {| @natural | [ @ident ] } : } %{
- %}
-
- .. todo
- See https://github.com/coq/coq/issues/12004 and
- https://github.com/coq/coq/issues/12825.
-
- ``{`` (without a terminating period) focuses on the first
- goal. The subproof can only be
- unfocused when it has been fully solved (*i.e.*, when there is no
- focused goal left). Unfocusing is then handled by ``}`` (again, without a
- terminating period). See also an example in the next section.
-
- Note that when a focused goal is proved a message is displayed
- together with a suggestion about the right bullet or ``}`` to unfocus it
- or focus the next one.
-
- :n:`@natural:`
- Focuses on the :token:`natural`\-th subgoal to prove.
-
- :n:`[ @ident ]: %{`
- Focuses on the named goal :token:`ident`.
-
- .. note::
-
- Goals are just existential variables and existential variables do not
- get a name by default. You can give a name to a goal by using :n:`refine ?[@ident]`.
- You may also wrap this in an Ltac-definition like:
-
- .. coqtop:: in
-
- Ltac name_goal name := refine ?[name].
-
- .. seealso:: :ref:`existential-variables`
-
- .. example::
-
- This first example uses the Ltac definition above, and the named goals
- only serve for documentation.
-
- .. coqtop:: all
-
- Goal forall n, n + 0 = n.
- Proof.
- induction n; [ name_goal base | name_goal step ].
- [base]: {
-
- .. coqtop:: all
-
- reflexivity.
-
- .. coqtop:: in
-
- }
-
- .. coqtop:: all
-
- [step]: {
-
- .. coqtop:: all
-
- simpl.
- f_equal.
- assumption.
- }
- Qed.
-
- This can also be a way of focusing on a shelved goal, for instance:
-
- .. coqtop:: all
-
- Goal exists n : nat, n = n.
- eexists ?[x].
- reflexivity.
- [x]: exact 0.
- Qed.
-
- .. exn:: This proof is focused, but cannot be unfocused this way.
-
- You are trying to use ``}`` but the current subproof has not been fully solved.
-
- .. exn:: No such goal (@natural).
- :undocumented:
-
- .. exn:: No such goal (@ident).
- :undocumented:
-
- .. exn:: Brackets do not support multi-goal selectors.
-
- Brackets are used to focus on a single goal given either by its position
- or by its name if it has one.
-
- .. seealso:: The error messages for bullets below.
-
-.. _bullets:
-
-Bullets
-```````
-
-Alternatively, proofs can be structured with bullets instead of ``{`` and ``}``. The
-use of a bullet ``b`` for the first time focuses on the first goal ``g``, the
-same bullet cannot be used again until the proof of ``g`` is completed,
-then it is mandatory to focus the next goal with ``b``. The consequence is
-that ``g`` and all goals present when ``g`` was focused are focused with the
-same bullet ``b``. See the example below.
-
-Different bullets can be used to nest levels. The scope of bullet does
-not go beyond enclosing ``{`` and ``}``, so bullets can be reused as further
-nesting levels provided they are delimited by these. Bullets are made of
-repeated ``-``, ``+`` or ``*`` symbols:
-
-.. prodn:: bullet ::= {| {+ - } | {+ + } | {+ * } }
-
-Note again that when a focused goal is proved a message is displayed
-together with a suggestion about the right bullet or ``}`` to unfocus it
-or focus the next one.
-
-.. note::
-
- In Proof General (``Emacs`` interface to |Coq|), you must use
- bullets with the priority ordering shown above to have a correct
- indentation. For example ``-`` must be the outer bullet and ``**`` the inner
- one in the example below.
-
-The following example script illustrates all these features:
-
-.. example::
-
- .. coqtop:: all
-
- Goal (((True /\ True) /\ True) /\ True) /\ True.
- Proof.
- split.
- - split.
- + split.
- ** { split.
- - trivial.
- - trivial.
- }
- ** trivial.
- + trivial.
- - assert True.
- { trivial. }
- assumption.
- Qed.
-
-.. exn:: Wrong bullet @bullet__1: Current bullet @bullet__2 is not finished.
-
- Before using bullet :n:`@bullet__1` again, you should first finish proving
- the current focused goal.
- Note that :n:`@bullet__1` and :n:`@bullet__2` may be the same.
-
-.. exn:: Wrong bullet @bullet__1: Bullet @bullet__2 is mandatory here.
-
- You must put :n:`@bullet__2` to focus on the next goal. No other bullet is
- allowed here.
-
-.. exn:: No such goal. Focus next goal with bullet @bullet.
-
- You tried to apply a tactic but no goals were under focus.
- Using :n:`@bullet` is mandatory here.
-
-.. FIXME: the :noindex: below works around a Sphinx issue.
- (https://github.com/sphinx-doc/sphinx/issues/4979)
- It should be removed once that issue is fixed.
-
-.. exn:: No such goal. Try unfocusing with %}.
- :noindex:
-
- You just finished a goal focused by ``{``, you must unfocus it with ``}``.
-
-Mandatory Bullets
-`````````````````
-
-Using :opt:`Default Goal Selector` with the ``!`` selector forces
-tactic scripts to keep focus to exactly one goal (e.g. using bullets)
-or use explicit goal selectors.
-
-Set Bullet Behavior
-```````````````````
-.. opt:: Bullet Behavior {| "None" | "Strict Subproofs" }
- :name: Bullet Behavior
-
- This option controls the bullet behavior and can take two possible values:
-
- - "None": this makes bullets inactive.
- - "Strict Subproofs": this makes bullets active (this is the default behavior).
-
-.. _requestinginformation:
-
-Requesting information
-----------------------
-
-
-.. cmd:: Show {? {| @ident | @natural } }
-
- Displays the current goals.
-
- :n:`@natural`
- Display only the :token:`natural`\-th subgoal.
-
- :n:`@ident`
- Displays the named goal :token:`ident`. This is useful in
- particular to display a shelved goal but only works if the
- corresponding existential variable has been named by the user
- (see :ref:`existential-variables`) as in the following example.
-
- .. example::
-
- .. coqtop:: all abort
-
- Goal exists n, n = 0.
- eexists ?[n].
- Show n.
-
- .. exn:: No focused proof.
- :undocumented:
-
- .. exn:: No such goal.
- :undocumented:
-
-.. cmd:: Show Proof {? Diffs {? removed } }
-
- Displays the proof term generated by the tactics
- that have been applied so far. If the proof is incomplete, the term
- will contain holes, which correspond to subterms which are still to be
- constructed. Each hole is an existential variable, which appears as a
- question mark followed by an identifier.
-
- Specifying “Diffs” highlights the difference between the
- current and previous proof step. By default, the command shows the
- output once with additions highlighted. Including “removed” shows
- the output twice: once showing removals and once showing additions.
- It does not examine the :opt:`Diffs` option. See :ref:`showing_proof_diffs`.
-
-.. cmd:: Show Conjectures
-
- Prints the names of all the
- theorems that are currently being proved. As it is possible to start
- proving a previous lemma during the proof of a theorem, there may
- be multiple names.
-
-.. cmd:: Show Intro
-
- If the current goal begins by at least one product,
- prints the name of the first product as it would be
- generated by an anonymous :tacn:`intro`. The aim of this command is to ease
- the writing of more robust scripts. For example, with an appropriate
- Proof General macro, it is possible to transform any anonymous :tacn:`intro`
- into a qualified one such as ``intro y13``. In the case of a non-product
- goal, it prints nothing.
-
-.. cmd:: Show Intros
-
- Similar to the previous command.
- Simulates the naming process of :tacn:`intros`.
-
-.. cmd:: Show Existentials
-
- Displays all open goals / existential variables in the current proof
- along with the type and the context of each variable.
-
-.. cmd:: Show Match @qualid
-
- Displays a template of the Gallina :token:`match<term_match>`
- construct with a branch for each constructor of the type
- :token:`qualid`. This is used internally by
- `company-coq <https://github.com/cpitclaudel/company-coq>`_.
-
- .. example::
-
- .. coqtop:: all
-
- Show Match nat.
-
- .. exn:: Unknown inductive type.
- :undocumented:
-
-.. cmd:: Show Universes
-
- Displays the set of all universe constraints and
- its normalized form at the current stage of the proof, useful for
- debugging universe inconsistencies.
-
-.. cmd:: Show Goal @natural at @natural
-
- Available in coqtop. Displays a goal at a
- proof state using the goal ID number and the proof state ID number.
- It is primarily for use by tools such as Prooftree that need to fetch
- goal history in this way. Prooftree is a tool for visualizing a proof
- as a tree that runs in Proof General.
-
-.. cmd:: Guarded
-
- Some tactics (e.g. :tacn:`refine`) allow to build proofs using
- fixpoint or co-fixpoint constructions. Due to the incremental nature
- of interactive proof construction, the check of the termination (or
- guardedness) of the recursive calls in the fixpoint or cofixpoint
- constructions is postponed to the time of the completion of the proof.
-
- The command :cmd:`Guarded` allows checking if the guard condition for
- fixpoint and cofixpoint is violated at some time of the construction
- of the proof without having to wait the completion of the proof.
-
-.. _showing_diffs:
-
-Showing differences between proof steps
----------------------------------------
-
-|Coq| can automatically highlight the differences between successive proof steps
-and between values in some error messages. |Coq| can also highlight differences
-in the proof term.
-For example, the following screenshots of |CoqIDE| and coqtop show the application
-of the same :tacn:`intros` tactic. The tactic creates two new hypotheses, highlighted in green.
-The conclusion is entirely in pale green because although it’s changed, no tokens were added
-to it. The second screenshot uses the "removed" option, so it shows the conclusion a
-second time with the old text, with deletions marked in red. Also, since the hypotheses are
-new, no line of old text is shown for them.
-
-.. comment screenshot produced with:
- Inductive ev : nat -> Prop :=
- | ev_0 : ev 0
- | ev_SS : forall n : nat, ev n -> ev (S (S n)).
-
- Fixpoint double (n:nat) :=
- match n with
- | O => O
- | S n' => S (S (double n'))
- end.
-
- Goal forall n, ev n -> exists k, n = double k.
- intros n E.
-
-..
-
- .. image:: ../_static/diffs-coqide-on.png
- :alt: |CoqIDE| with Set Diffs on
-
-..
-
- .. image:: ../_static/diffs-coqide-removed.png
- :alt: |CoqIDE| with Set Diffs removed
-
-..
-
- .. image:: ../_static/diffs-coqtop-on3.png
- :alt: coqtop with Set Diffs on
-
-This image shows an error message with diff highlighting in |CoqIDE|:
-
-..
-
- .. image:: ../_static/diffs-error-message.png
- :alt: |CoqIDE| error message with diffs
-
-How to enable diffs
-```````````````````
-
-.. opt:: Diffs {| "on" | "off" | "removed" }
- :name: Diffs
-
- The “on” setting highlights added tokens in green, while the “removed” setting
- additionally reprints items with removed tokens in red. Unchanged tokens in
- modified items are shown with pale green or red. Diffs in error messages
- use red and green for the compared values; they appear regardless of the setting.
- (Colors are user-configurable.)
-
-For coqtop, showing diffs can be enabled when starting coqtop with the
-``-diffs on|off|removed`` command-line option or by setting the :opt:`Diffs` option
-within |Coq|. You will need to provide the ``-color on|auto`` command-line option when
-you start coqtop in either case.
-
-Colors for coqtop can be configured by setting the ``COQ_COLORS`` environment
-variable. See section :ref:`customization-by-environment-variables`. Diffs
-use the tags ``diff.added``, ``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg``.
-
-In |CoqIDE|, diffs should be enabled from the ``View`` menu. Don’t use the ``Set Diffs``
-command in |CoqIDE|. You can change the background colors shown for diffs from the
-``Edit | Preferences | Tags`` panel by changing the settings for the ``diff.added``,
-``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg`` tags. This panel also
-lets you control other attributes of the highlights, such as the foreground
-color, bold, italic, underline and strikeout.
-
-Proof General can also display |Coq|-generated proof diffs automatically.
-Please see the PG documentation section
-"`Showing Proof Diffs" <https://proofgeneral.github.io/doc/master/userman/Coq-Proof-General#Showing-Proof-Diffs>`_)
-for details.
-
-How diffs are calculated
-````````````````````````
-
-Diffs are calculated as follows:
-
-1. Select the old proof state to compare to, which is the proof state before
- the last tactic that changed the proof. Changes that only affect the view
- of the proof, such as ``all: swap 1 2``, are ignored.
-
-2. For each goal in the new proof state, determine what old goal to compare
- it to—the one it is derived from or is the same as. Match the hypotheses by
- name (order is ignored), handling compacted items specially.
-
-3. For each hypothesis and conclusion (the “items”) in each goal, pass
- them as strings to the lexer to break them into tokens. Then apply the
- Myers diff algorithm :cite:`Myers` on the tokens and add appropriate highlighting.
-
-Notes:
-
-* Aside from the highlights, output for the "on" option should be identical
- to the undiffed output.
-* Goals completed in the last proof step will not be shown even with the
- "removed" setting.
-
-.. comment The following screenshots show diffs working with multiple goals and with compacted
- hypotheses. In the first one, notice that the goal ``P 1`` is not highlighted at
- all after the split because it has not changed.
-
- .. todo: Use this script and remove the screenshots when COQ_COLORS
- works for coqtop in sphinx
- .. coqtop:: none
-
- Set Diffs "on".
- Parameter P : nat -> Prop.
- Goal P 1 /\ P 2 /\ P 3.
-
- .. coqtop:: out
-
- split.
-
- .. coqtop:: all abort
-
- 2: split.
-
- ..
-
- .. coqtop:: none
-
- Set Diffs "on".
- Goal forall n m : nat, n + m = m + n.
- Set Diffs "on".
-
- .. coqtop:: out
-
- intros n.
-
- .. coqtop:: all abort
-
- intros m.
-
-This screen shot shows the result of applying a :tacn:`split` tactic that replaces one goal
-with 2 goals. Notice that the goal ``P 1`` is not highlighted at all after
-the split because it has not changed.
-
-..
-
- .. image:: ../_static/diffs-coqide-multigoal.png
- :alt: coqide with Set Diffs on with multiple goals
-
-Diffs may appear like this after applying a :tacn:`intro` tactic that results
-in a compacted hypotheses:
-
-..
-
- .. image:: ../_static/diffs-coqide-compacted.png
- :alt: coqide with Set Diffs on with compacted hypotheses
-
-.. _showing_proof_diffs:
-
-"Show Proof" differences
-````````````````````````
-
-To show differences in the proof term:
-
-- In coqtop and Proof General, use the :cmd:`Show Proof` `Diffs` command.
-
-- In |CoqIDE|, position the cursor on or just after a tactic to compare the proof term
- after the tactic with the proof term before the tactic, then select
- `View / Show Proof` from the menu or enter the associated key binding.
- Differences will be shown applying the current `Show Diffs` setting
- from the `View` menu. If the current setting is `Don't show diffs`, diffs
- will not be shown.
-
- Output with the "added and removed" option looks like this:
-
- ..
-
- .. image:: ../_static/diffs-show-proof.png
- :alt: coqide with Set Diffs on with compacted hypotheses
-
-Controlling the effect of proof editing commands
-------------------------------------------------
-
-
-.. opt:: Hyps Limit @natural
- :name: Hyps Limit
-
- This option controls the maximum number of hypotheses displayed in goals
- after the application of a tactic. All the hypotheses remain usable
- in the proof development.
- When unset, it goes back to the default mode which is to print all
- available hypotheses.
-
-
-.. flag:: Nested Proofs Allowed
-
- When turned on (it is off by default), this flag enables support for nested
- proofs: a new assertion command can be inserted before the current proof is
- finished, in which case |Coq| will temporarily switch to the proof of this
- *nested lemma*. When the proof of the nested lemma is finished (with :cmd:`Qed`
- or :cmd:`Defined`), its statement will be made available (as if it had been
- proved before starting the previous proof) and |Coq| will switch back to the
- proof of the previous assertion.
-
-.. flag:: Printing Goal Names
-
- When turned on, the name of the goal is printed in interactive
- proof mode, which can be useful in cases of cross references
- between goals.
-
-Controlling memory usage
-------------------------
-
-.. cmd:: Print Debug GC
-
- Prints heap usage statistics, which are values from the `stat` type of the `Gc` module
- described
- `here <https://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#TYPEstat>`_
- in the |OCaml| documentation.
- The `live_words`, `heap_words` and `top_heap_words` values give the basic information.
- Words are 8 bytes or 4 bytes, respectively, for 64- and 32-bit executables.
-
-When experiencing high memory usage the following commands can be used
-to force |Coq| to optimize some of its internal data structures.
-
-.. cmd:: Optimize Proof
-
- Shrink the data structure used to represent the current proof.
-
-
-.. cmd:: Optimize Heap
-
- Perform a heap compaction. This is generally an expensive operation.
- See: `|OCaml| Gc.compact <http://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#VALcompact>`_
- There is also an analogous tactic :tacn:`optimize_heap`.
-
-Memory usage parameters can be set through the :ref:`OCAMLRUNPARAM <OCAMLRUNPARAM>`
-environment variable.
+ <meta http-equiv="refresh" content="0;URL=../proofs/writing-proofs/proof-mode.html">
diff --git a/doc/sphinx/proof-engine/ssreflect-proof-language.rst b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
index cdbae8ade1..07c2d268c6 100644
--- a/doc/sphinx/proof-engine/ssreflect-proof-language.rst
+++ b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
@@ -13,12 +13,12 @@ Introduction
This chapter describes a set of tactics known as |SSR| originally
designed to provide support for the so-called *small scale reflection*
proof methodology. Despite the original purpose this set of tactic is
-of general interest and is available in |Coq| starting from version 8.7.
+of general interest and is available in Coq starting from version 8.7.
|SSR| was developed independently of the tactics described in
Chapter :ref:`tactics`. Indeed the scope of the tactics part of |SSR| largely
overlaps with the standard set of tactics. Eventually the overlap will
-be reduced in future releases of |Coq|.
+be reduced in future releases of Coq.
Proofs written in |SSR| typically look quite different from the
ones written using only tactics as per Chapter :ref:`tactics`. We try to
@@ -112,7 +112,7 @@ Compatibility issues
~~~~~~~~~~~~~~~~~~~~
Requiring the above modules creates an environment which is mostly
-compatible with the rest of |Coq|, up to a few discrepancies:
+compatible with the rest of Coq, up to a few discrepancies:
+ New keywords (``is``) might clash with variable, constant, tactic or
@@ -124,11 +124,11 @@ compatible with the rest of |Coq|, up to a few discrepancies:
+ Identifiers with both leading and trailing ``_``, such as ``_x_``, are
reserved by |SSR| and cannot appear in scripts.
+ The extensions to the :tacn:`rewrite` tactic are partly incompatible with those
- available in current versions of |Coq|; in particular: ``rewrite .. in
+ available in current versions of Coq; in particular: ``rewrite .. in
(type of k)`` or ``rewrite .. in *`` or any other variant of :tacn:`rewrite`
will not work, and the |SSR| syntax and semantics for occurrence selection
and rule chaining is different. Use an explicit rewrite direction
- (``rewrite <- …`` or ``rewrite -> …``) to access the |Coq| rewrite tactic.
+ (``rewrite <- …`` or ``rewrite -> …``) to access the Coq rewrite tactic.
+ New symbols (``//``, ``/=``, ``//=``) might clash with adjacent
existing symbols.
This can be avoided by inserting white spaces.
@@ -158,34 +158,34 @@ compatible with the rest of |Coq|, up to a few discrepancies:
generalized form, turn off the |SSR| Boolean ``if`` notation using the command:
``Close Scope boolean_if_scope``.
+ The following flags can be unset to make |SSR| more compatible with
- parts of |Coq|:
+ parts of Coq:
.. flag:: SsrRewrite
Controls whether the incompatible rewrite syntax is enabled (the default).
- Disabling the flag makes the syntax compatible with other parts of |Coq|.
+ Disabling the flag makes the syntax compatible with other parts of Coq.
.. flag:: SsrIdents
Controls whether tactics can refer to |SSR|-generated variables that are
in the form _xxx_. Scripts with explicit references to such variables
are fragile; they are prone to failure if the proof is later modified or
- if the details of variable name generation change in future releases of |Coq|.
+ if the details of variable name generation change in future releases of Coq.
The default is on, which gives an error message when the user tries to
create such identifiers. Disabling the flag generates a warning instead,
- increasing compatibility with other parts of |Coq|.
+ increasing compatibility with other parts of Coq.
-|Gallina| extensions
+Gallina extensions
--------------------
Small-scale reflection makes an extensive use of the programming
-subset of |Gallina|, |Coq|’s logical specification language. This subset
+subset of Gallina, Coq’s logical specification language. This subset
is quite suited to the description of functions on representations,
because it closely follows the well-established design of the ML
programming language. The |SSR| extension provides three additions
-to |Gallina|, for pattern assignment, pattern testing, and polymorphism;
-these mitigate minor but annoying discrepancies between |Gallina| and
+to Gallina, for pattern assignment, pattern testing, and polymorphism;
+these mitigate minor but annoying discrepancies between Gallina and
ML.
@@ -199,7 +199,7 @@ irrefutable pattern matching, that is, destructuring assignment:
term += let: @pattern := @term in @term
Note the colon ``:`` after the ``let`` keyword, which avoids any ambiguity
-with a function definition or |Coq|’s basic destructuring let. The let:
+with a function definition or Coq’s basic destructuring let. The let:
construct differs from the latter in that
@@ -237,7 +237,7 @@ construct differs from the latter in that
The ``let:`` construct is just (more legible) notation for the primitive
-|Gallina| expression :n:`match @term with @pattern => @term end`.
+Gallina expression :n:`match @term with @pattern => @term end`.
The |SSR| destructuring assignment supports all the dependent
match annotations; the full syntax is
@@ -294,10 +294,10 @@ example, the null and all list function(al)s can be defined as follows:
The pattern conditional also provides a notation for destructuring
assignment with a refutable pattern, adapted to the pure functional
-setting of |Gallina|, which lacks a ``Match_Failure`` exception.
+setting of Gallina, which lacks a ``Match_Failure`` exception.
Like ``let:`` above, the ``if…is`` construct is just (more legible) notation
-for the primitive |Gallina| expression
+for the primitive Gallina expression
:n:`match @term with @pattern => @term | _ => @term end`.
Similarly, it will always be displayed as the expansion of this form
@@ -355,15 +355,15 @@ Note that :token:`pattern` eventually binds variables in the third
Parametric polymorphism
~~~~~~~~~~~~~~~~~~~~~~~
-Unlike ML, polymorphism in core |Gallina| is explicit: the type
+Unlike ML, polymorphism in core Gallina is explicit: the type
parameters of polymorphic functions must be declared explicitly, and
-supplied at each point of use. However, |Coq| provides two features to
+supplied at each point of use. However, Coq provides two features to
suppress redundant parameters:
+ Sections are used to provide (possibly implicit) parameters for a
set of definitions.
-+ Implicit arguments declarations are used to tell |Coq| to use type
++ Implicit arguments declarations are used to tell Coq to use type
inference to deduce some parameters from the context at each point of
call.
@@ -392,11 +392,11 @@ expressions such as
Definition all_null (s : list T) := all (@null T) s.
Unfortunately, such higher-order expressions are quite frequent in
-representation functions, especially those which use |Coq|'s
+representation functions, especially those which use Coq's
``Structures`` to emulate Haskell typeclasses.
-Therefore, |SSR| provides a variant of |Coq|’s implicit argument
-declaration, which causes |Coq| to fill in some implicit parameters at
+Therefore, |SSR| provides a variant of Coq’s implicit argument
+declaration, which causes Coq to fill in some implicit parameters at
each point of use, e.g., the above definition can be written:
.. example::
@@ -432,7 +432,7 @@ The syntax of the new declaration is
As these prenex implicit arguments are ubiquitous and have often large
display strings, it is strongly recommended to change the default
- display settings of |Coq| so that they are not printed (except after
+ display settings of Coq so that they are not printed (except after
a ``Set Printing All`` command). All |SSR| library files thus start
with the incantation
@@ -957,7 +957,7 @@ context. This is essential in the context of an interactive
development environment (IDE), because it facilitates navigating the
proof, allowing to instantly "jump back" to the point at which a
questionable assumption was added, and to find relevant assumptions by
-browsing the pruned context. While novice or casual |Coq| users may find
+browsing the pruned context. While novice or casual Coq users may find
the automatic name selection feature convenient, the usage of such a
feature severely undermines the readability and maintainability of
proof scripts, much like automatic variable declaration in programming
@@ -973,7 +973,7 @@ the foundation of the |SSR| proof language.
Bookkeeping
~~~~~~~~~~~
-During the course of a proof |Coq| always present the user with a
+During the course of a proof Coq always present the user with a
*sequent* whose general form is::
ci : Ti
@@ -1015,7 +1015,7 @@ are *ordered*, but *unnamed*: the display names of variables may
change at any time because of α-conversion.
Similarly, basic deductive steps such as apply can only operate on the
-goal because the |Gallina| terms that control their action (e.g., the
+goal because the Gallina terms that control their action (e.g., the
type of the lemma used by ``apply``) only provide unnamed bound variables.
[#2]_ Since the proof script can only refer directly to the context, it
must constantly shift declarations from the goal to the context and
@@ -1083,7 +1083,7 @@ simultaneously renames ``m`` and ``le_m_n`` into ``p`` and ``le_n_p``,
respectively, by first turning them into unnamed variables, then
turning these variables back into constants and facts.
-Furthermore, |SSR| redefines the basic |Coq| tactics ``case``, ``elim``,
+Furthermore, |SSR| redefines the basic Coq tactics ``case``, ``elim``,
and ``apply`` so that they can take better advantage of
``:`` and ``=>``. In there
|SSR| variants, these tactic operate on the first variable or
@@ -1421,7 +1421,7 @@ Therefore this tactic changes any goal ``G`` into
forall n n0 : nat, n = n0 -> G.
-where the name ``n0`` is picked by the |Coq| display function, and assuming
+where the name ``n0`` is picked by the Coq display function, and assuming
``n`` appeared only in ``G``.
Finally, note that a discharge operation generalizes defined constants
@@ -1647,7 +1647,10 @@ Notations can be used to name tactics, for example
Notation "'myop'" := (ltac:(my ltac code)) : ssripat_scope.
lets one write just ``/myop`` in the intro pattern. Note the scope
-annotation: views are interpreted opening the ``ssripat`` scope.
+annotation: views are interpreted opening the ``ssripat`` scope. We
+provide the following ltac views: ``/[dup]`` to duplicate the top of
+the stack, ``/[swap]`` to swap the two first elements and ``/[apply]``
+to apply the top of the stack to the next.
Intro patterns
``````````````
@@ -1927,7 +1930,7 @@ When the top assumption of a goal has an inductive type, two specific
operations are possible: the case analysis performed by the :tacn:`case`
tactic, and the application of an induction principle, performed by
the :tacn:`elim` tactic. When this top assumption has an inductive type, which
-is moreover an instance of a type family, |Coq| may need help from the
+is moreover an instance of a type family, Coq may need help from the
user to specify which occurrences of the parameters of the type should
be substituted.
@@ -2055,7 +2058,7 @@ Control flow
Indentation and bullets
~~~~~~~~~~~~~~~~~~~~~~~
-A linear development of |Coq| scripts gives little information on the
+A linear development of Coq scripts gives little information on the
structure of the proof. In addition, replaying a proof after some
changes in the statement to be proved will usually not display
information to distinguish between the various branches of case
@@ -3391,7 +3394,7 @@ rewrite operations prescribed by the rules on the current goal.
Indeed rule ``eqab`` is the first to apply among the ones
gathered in the tuple passed to the rewrite tactic. This multirule
- ``(eqab, eqac)`` is actually a |Coq| term and we can name it with a
+ ``(eqab, eqac)`` is actually a Coq term and we can name it with a
definition:
.. coqtop:: all
@@ -3529,11 +3532,11 @@ Anyway this tactic is *not* equivalent to
lemma that was used, while the latter requires you prove the quantified
form.
-When |SSR| rewrite fails on standard |Coq| licit rewrite
+When |SSR| rewrite fails on standard Coq licit rewrite
````````````````````````````````````````````````````````
In a few cases, the |SSR| rewrite tactic fails rewriting some
-redexes which standard |Coq| successfully rewrites. There are two main
+redexes which standard Coq successfully rewrites. There are two main
cases:
@@ -3550,7 +3553,7 @@ cases:
Lemma fubar (x : unit) : (let u := x in u) = tt.
-+ The standard rewrite tactic provided by |Coq| uses a different algorithm
++ The standard rewrite tactic provided by Coq uses a different algorithm
to find instances of the rewrite rule.
.. example::
@@ -3953,7 +3956,7 @@ together with “term tagging” operations.
The first one uses auxiliary definitions to introduce a provably equal
copy of any term t. However this copy is (on purpose) *not
-convertible* to t in the |Coq| system [#8]_. The job is done by the
+convertible* to t in the Coq system [#8]_. The job is done by the
following construction:
.. coqdoc::
@@ -4542,7 +4545,7 @@ is a synonym for:
elim x using V; clear x; intro y.
where ``x`` is a variable in the context, ``y`` a fresh name and ``V``
-any second order lemma; |SSR| relaxes the syntactic restrictions of the |Coq|
+any second order lemma; |SSR| relaxes the syntactic restrictions of the Coq
``elim``. The first pattern following ``:`` can be a ``_`` wildcard if the
conclusion of the view ``V`` specifies a pattern for its last argument
(e.g., if ``V`` is a functional induction lemma generated by the
@@ -4590,7 +4593,7 @@ generation (see section :ref:`generation_of_equations_ssr`).
elim/last_ind_list E : l=> [| u v]; last first.
-User-provided eliminators (potentially generated with |Coq|’s ``Function``
+User-provided eliminators (potentially generated with Coq’s ``Function``
command) can be combined with the type family switches described
in section :ref:`type_families_ssr`.
Consider an eliminator ``foo_ind`` of type:
@@ -4982,8 +4985,8 @@ distinction between logical propositions and boolean values. On the
one hand, logical propositions are objects of *sort* ``Prop`` which is
the carrier of intuitionistic reasoning. Logical connectives in
``Prop`` are *types*, which give precise information on the structure
-of their proofs; this information is automatically exploited by |Coq|
-tactics. For example, |Coq| knows that a proof of ``A \/ B`` is
+of their proofs; this information is automatically exploited by Coq
+tactics. For example, Coq knows that a proof of ``A \/ B`` is
either a proof of ``A`` or a proof of ``B``. The tactics ``left`` and
``right`` change the goal ``A \/ B`` to ``A`` and ``B``, respectively;
dually, the tactic ``case`` reduces the goal ``A \/ B => G`` to two
@@ -5042,7 +5045,7 @@ mechanism:
Coercion is_true (b : bool) := b = true.
-This allows any boolean formula ``b`` to be used in a context where |Coq|
+This allows any boolean formula ``b`` to be used in a context where Coq
would expect a proposition, e.g., after ``Lemma … :``. It is then
interpreted as ``(is_true b)``, i.e., the proposition ``b = true``. Coercions
are elided by the pretty-printer, so they are essentially transparent
@@ -5077,9 +5080,9 @@ proposition ``b1 /\ b2`` hides two coercions. The conjunction of
Expressing logical equivalences through this family of inductive types
makes possible to take benefit from *rewritable equations* associated
-to the case analysis of |Coq|’s inductive types.
+to the case analysis of Coq’s inductive types.
-Since the equivalence predicate is defined in |Coq| as:
+Since the equivalence predicate is defined in Coq as:
.. coqdoc::
@@ -5573,7 +5576,7 @@ Natural number
.. prodn:: nat_or_ident ::= {| @natural | @ident }
-where :token:`ident` is an Ltac variable denoting a standard |Coq| number
+where :token:`ident` is an Ltac variable denoting a standard Coq number
(should not be the name of a tactic which can be followed by a
bracket ``[``, like ``do``, ``have``,…)
@@ -5823,6 +5826,6 @@ Settings
.. [#8] This is an implementation feature: there is no such obstruction
in the metatheory
.. [#9] The current state of the proof shall be displayed by the Show
- Proof command of |Coq| proof mode.
+ Proof command of Coq proof mode.
.. [#10] A simple proof context entry is a naked identifier (i.e. not between
parentheses) designating a context entry that is not a section variable.
diff --git a/doc/sphinx/proof-engine/tactics.rst b/doc/sphinx/proof-engine/tactics.rst
index fe9a31e220..26a56005c1 100644
--- a/doc/sphinx/proof-engine/tactics.rst
+++ b/doc/sphinx/proof-engine/tactics.rst
@@ -167,11 +167,11 @@ The :n:`eqn:` construct in various tactics uses :n:`@naming_intropattern`.
Use these elementary patterns to specify a name:
* :n:`@ident` — use the specified name
-* :n:`?` — let |Coq| choose a name
+* :n:`?` — let Coq choose a name
* :n:`?@ident` — generate a name that begins with :n:`@ident`
* :n:`_` — discard the matched part (unless it is required for another
hypothesis)
-* if a disjunction pattern omits a name, such as :g:`[|H2]`, |Coq| will choose a name
+* if a disjunction pattern omits a name, such as :g:`[|H2]`, Coq will choose a name
**Splitting patterns**
@@ -268,7 +268,7 @@ These patterns can be used when the hypothesis is an equality:
For :n:`intros @intropattern_list`, controls how to handle a
conjunctive pattern that doesn't give enough simple patterns to match
- all the arguments in the constructor. If set (the default), |Coq| generates
+ all the arguments in the constructor. If set (the default), Coq generates
additional names to match the number of arguments.
Unsetting the flag will put the additional hypotheses in the goal instead, behavior that is more
similar to |SSR|'s intro patterns.
@@ -843,7 +843,7 @@ Applying theorems
.. flag:: Universal Lemma Under Conjunction
- This flag, which preserves compatibility with versions of |Coq| prior to
+ This flag, which preserves compatibility with versions of Coq prior to
8.4 is also available for :n:`apply @term in @ident` (see :tacn:`apply … in`).
.. tacn:: apply @term in @ident
@@ -1293,7 +1293,7 @@ Managing the local context
.. tacv:: set @term {? in @goal_occurrences }
This behaves as :n:`set (@ident := @term) {? in @goal_occurrences }`
- but :token:`ident` is generated by |Coq|.
+ but :token:`ident` is generated by Coq.
.. tacv:: eset (@ident {* @binder } := @term) {? in @goal_occurrences }
eset @term {? in @goal_occurrences }
@@ -1338,7 +1338,7 @@ Managing the local context
.. tacv:: pose @term
This behaves as :n:`pose (@ident := @term)` but :token:`ident` is
- generated by |Coq|.
+ generated by Coq.
.. tacv:: epose (@ident {* @binder } := @term)
epose @term
@@ -1400,7 +1400,7 @@ Controlling the proof flow
.. tacv:: assert @type
This behaves as :n:`assert (@ident : @type)` but :n:`@ident` is
- generated by |Coq|.
+ generated by Coq.
.. tacv:: assert @type by @tactic
@@ -1480,7 +1480,7 @@ Controlling the proof flow
.. tacv:: enough @type
This behaves like :n:`enough (@ident : @type)` with the name :token:`ident` of
- the hypothesis generated by |Coq|.
+ the hypothesis generated by Coq.
.. tacv:: enough @type as @simple_intropattern
@@ -1605,7 +1605,7 @@ name of the variable (here :g:`n`) is chosen based on :g:`T`.
must have given the name explicitly (see :ref:`Existential-Variables`).
.. note:: When you are referring to hypotheses which you did not name
- explicitly, be aware that |Coq| may make a different decision on how to
+ explicitly, be aware that Coq may make a different decision on how to
name the variable in the current goal and in the context of the
existential variable. This can lead to surprising behaviors.
@@ -1759,7 +1759,7 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
between :token:`term` and the value that it takes in each of the
possible cases. The name of the equation is specified
by :token:`naming_intropattern` (see :tacn:`intros`),
- in particular ``?`` can be used to let |Coq| generate a fresh name.
+ in particular ``?`` can be used to let Coq generate a fresh name.
.. tacv:: destruct @term with @bindings
@@ -2353,7 +2353,7 @@ and an explanation of the underlying technique.
``inversion`` generally behaves in a slightly more expectable way than
``inversion`` (no artificial duplication of some hypotheses referring to
other hypotheses). To take benefit of these improvements, it is enough to use
- ``inversion ... as []``, letting the names being finally chosen by |Coq|.
+ ``inversion ... as []``, letting the names being finally chosen by Coq.
.. example::
@@ -2663,1760 +2663,6 @@ and an explanation of the underlying technique.
simultaneously proved are respectively :g:`forall binder ... binder, type`
The identifiers :n:`@ident` are the names of the coinduction hypotheses.
-.. _rewritingexpressions:
-
-Rewriting expressions
----------------------
-
-These tactics use the equality :g:`eq:forall A:Type, A->A->Prop` defined in
-file ``Logic.v`` (see :ref:`coq-library-logic`). The notation for :g:`eq T t u` is
-simply :g:`t=u` dropping the implicit type of :g:`t` and :g:`u`.
-
-.. tacn:: rewrite @term
- :name: rewrite
-
- This tactic applies to any goal. The type of :token:`term` must have the form
-
- ``forall (x``:sub:`1` ``:A``:sub:`1` ``) ... (x``:sub:`n` ``:A``:sub:`n` ``), eq term``:sub:`1` ``term``:sub:`2` ``.``
-
- where :g:`eq` is the Leibniz equality or a registered setoid equality.
-
- Then :n:`rewrite @term` finds the first subterm matching `term`\ :sub:`1` in the goal,
- resulting in instances `term`:sub:`1`' and `term`:sub:`2`' and then
- replaces every occurrence of `term`:subscript:`1`' by `term`:subscript:`2`'.
- Hence, some of the variables :g:`x`\ :sub:`i` are solved by unification,
- and some of the types :g:`A`\ :sub:`1`:g:`, ..., A`\ :sub:`n` become new
- subgoals.
-
- .. exn:: The @term provided does not end with an equation.
- :undocumented:
-
- .. exn:: Tactic generated a subgoal identical to the original goal. This happens if @term does not occur in the goal.
- :undocumented:
-
- .. tacv:: rewrite -> @term
-
- Is equivalent to :n:`rewrite @term`
-
- .. tacv:: rewrite <- @term
-
- Uses the equality :n:`@term`:sub:`1` :n:`= @term` :sub:`2` from right to left
-
- .. tacv:: rewrite @term in @goal_occurrences
-
- Analogous to :n:`rewrite @term` but rewriting is done following
- the clause :token:`goal_occurrences`. For instance:
-
- + :n:`rewrite H in H'` will rewrite `H` in the hypothesis
- ``H'`` instead of the current goal.
- + :n:`rewrite H in H' at 1, H'' at - 2 |- *` means
- :n:`rewrite H; rewrite H in H' at 1; rewrite H in H'' at - 2.`
- In particular a failure will happen if any of these three simpler tactics
- fails.
- + :n:`rewrite H in * |-` will do :n:`rewrite H in H'` for all hypotheses
- :g:`H'` different from :g:`H`.
- A success will happen as soon as at least one of these simpler tactics succeeds.
- + :n:`rewrite H in *` is a combination of :n:`rewrite H` and :n:`rewrite H in * |-`
- that succeeds if at least one of these two tactics succeeds.
-
- Orientation :g:`->` or :g:`<-` can be inserted before the :token:`term` to rewrite.
-
- .. tacv:: rewrite @term at @occurrences
-
- Rewrite only the given :token:`occurrences` of :token:`term`. Occurrences are
- specified from left to right as for pattern (:tacn:`pattern`). The rewrite is
- always performed using setoid rewriting, even for Leibniz’s equality, so one
- has to ``Import Setoid`` to use this variant.
-
- .. tacv:: rewrite @term by @tactic
-
- Use tactic to completely solve the side-conditions arising from the
- :tacn:`rewrite`.
-
- .. tacv:: rewrite {+, @orientation @term} {? in @ident }
-
- Is equivalent to the `n` successive tactics :n:`{+; rewrite @term}`, each one
- working on the first subgoal generated by the previous one. An :production:`orientation`
- ``->`` or ``<-`` can be inserted before each :token:`term` to rewrite. One
- unique clause can be added at the end after the keyword in; it will then
- affect all rewrite operations.
-
- In all forms of rewrite described above, a :token:`term` to rewrite can be
- immediately prefixed by one of the following modifiers:
-
- + `?` : the tactic :n:`rewrite ?@term` performs the rewrite of :token:`term` as many
- times as possible (perhaps zero time). This form never fails.
- + :n:`@natural?` : works similarly, except that it will do at most :token:`natural` rewrites.
- + `!` : works as `?`, except that at least one rewrite should succeed, otherwise
- the tactic fails.
- + :n:`@natural!` (or simply :n:`@natural`) : precisely :token:`natural` rewrites of :token:`term` will be done,
- leading to failure if these :token:`natural` rewrites are not possible.
-
- .. tacv:: erewrite @term
- :name: erewrite
-
- This tactic works as :n:`rewrite @term` but turning
- unresolved bindings into existential variables, if any, instead of
- failing. It has the same variants as :tacn:`rewrite` has.
-
- .. flag:: Keyed Unification
-
- Makes higher-order unification used by :tacn:`rewrite` rely on a set of keys to drive
- unification. The subterms, considered as rewriting candidates, must start with
- the same key as the left- or right-hand side of the lemma given to rewrite, and the arguments
- are then unified up to full reduction.
-
-.. tacn:: replace @term with @term’
- :name: replace
-
- This tactic applies to any goal. It replaces all free occurrences of :n:`@term`
- in the current goal with :n:`@term’` and generates an equality :n:`@term = @term’`
- as a subgoal. This equality is automatically solved if it occurs among
- the assumptions, or if its symmetric form occurs. It is equivalent to
- :n:`cut @term = @term’; [intro H`:sub:`n` :n:`; rewrite <- H`:sub:`n` :n:`; clear H`:sub:`n`:n:`|| assumption || symmetry; try assumption]`.
-
- .. exn:: Terms do not have convertible types.
- :undocumented:
-
- .. tacv:: replace @term with @term’ by @tactic
-
- This acts as :n:`replace @term with @term’` but applies :token:`tactic` to solve the generated
- subgoal :n:`@term = @term’`.
-
- .. tacv:: replace @term
-
- Replaces :n:`@term` with :n:`@term’` using the first assumption whose type has
- the form :n:`@term = @term’` or :n:`@term’ = @term`.
-
- .. tacv:: replace -> @term
-
- Replaces :n:`@term` with :n:`@term’` using the first assumption whose type has
- the form :n:`@term = @term’`
-
- .. tacv:: replace <- @term
-
- Replaces :n:`@term` with :n:`@term’` using the first assumption whose type has
- the form :n:`@term’ = @term`
-
- .. tacv:: replace @term {? with @term} in @goal_occurrences {? by @tactic}
- replace -> @term in @goal_occurrences
- replace <- @term in @goal_occurrences
-
- Acts as before but the replacements take place in the specified clauses
- (:token:`goal_occurrences`) (see :ref:`performingcomputations`) and not
- only in the conclusion of the goal. The clause argument must not contain
- any ``type of`` nor ``value of``.
-
-.. tacn:: subst @ident
- :name: subst
-
- This tactic applies to a goal that has :n:`@ident` in its context and (at
- least) one hypothesis, say :g:`H`, of type :n:`@ident = t` or :n:`t = @ident`
- with :n:`@ident` not occurring in :g:`t`. Then it replaces :n:`@ident` by
- :g:`t` everywhere in the goal (in the hypotheses and in the conclusion) and
- clears :n:`@ident` and :g:`H` from the context.
-
- If :n:`@ident` is a local definition of the form :n:`@ident := t`, it is also
- unfolded and cleared.
-
- If :n:`@ident` is a section variable it is expected to have no
- indirect occurrences in the goal, i.e. that no global declarations
- implicitly depending on the section variable must be present in the
- goal.
-
- .. note::
- + When several hypotheses have the form :n:`@ident = t` or :n:`t = @ident`, the
- first one is used.
-
- + If :g:`H` is itself dependent in the goal, it is replaced by the proof of
- reflexivity of equality.
-
- .. tacv:: subst {+ @ident}
-
- This is equivalent to :n:`subst @ident`:sub:`1`:n:`; ...; subst @ident`:sub:`n`.
-
- .. tacv:: subst
-
- This applies :tacn:`subst` repeatedly from top to bottom to all hypotheses of the
- context for which an equality of the form :n:`@ident = t` or :n:`t = @ident`
- or :n:`@ident := t` exists, with :n:`@ident` not occurring in
- ``t`` and :n:`@ident` not a section variable with indirect
- dependencies in the goal.
-
- .. flag:: Regular Subst Tactic
-
- This flag controls the behavior of :tacn:`subst`. When it is
- activated (it is by default), :tacn:`subst` also deals with the following corner cases:
-
- + A context with ordered hypotheses :n:`@ident`:sub:`1` :n:`= @ident`:sub:`2`
- and :n:`@ident`:sub:`1` :n:`= t`, or :n:`t′ = @ident`:sub:`1`` with `t′` not
- a variable, and no other hypotheses of the form :n:`@ident`:sub:`2` :n:`= u`
- or :n:`u = @ident`:sub:`2`; without the flag, a second call to
- subst would be necessary to replace :n:`@ident`:sub:`2` by `t` or
- `t′` respectively.
- + The presence of a recursive equation which without the flag would
- be a cause of failure of :tacn:`subst`.
- + A context with cyclic dependencies as with hypotheses :n:`@ident`:sub:`1` :n:`= f @ident`:sub:`2`
- and :n:`@ident`:sub:`2` :n:`= g @ident`:sub:`1` which without the
- flag would be a cause of failure of :tacn:`subst`.
-
- Additionally, it prevents a local definition such as :n:`@ident := t` to be
- unfolded which otherwise it would exceptionally unfold in configurations
- containing hypotheses of the form :n:`@ident = u`, or :n:`u′ = @ident`
- with `u′` not a variable. Finally, it preserves the initial order of
- hypotheses, which without the flag it may break.
- default.
-
- .. exn:: Cannot find any non-recursive equality over :n:`@ident`.
- :undocumented:
-
- .. exn:: Section variable :n:`@ident` occurs implicitly in global declaration :n:`@qualid` present in hypothesis :n:`@ident`.
- Section variable :n:`@ident` occurs implicitly in global declaration :n:`@qualid` present in the conclusion.
-
- Raised when the variable is a section variable with indirect
- dependencies in the goal.
-
-
-.. tacn:: stepl @term
- :name: stepl
-
- This tactic is for chaining rewriting steps. It assumes a goal of the
- form :n:`R @term @term` where ``R`` is a binary relation and relies on a
- database of lemmas of the form :g:`forall x y z, R x y -> eq x z -> R z y`
- where `eq` is typically a setoid equality. The application of :n:`stepl @term`
- then replaces the goal by :n:`R @term @term` and adds a new goal stating
- :n:`eq @term @term`.
-
- .. cmd:: Declare Left Step @term
-
- Adds :n:`@term` to the database used by :tacn:`stepl`.
-
- This tactic is especially useful for parametric setoids which are not accepted
- as regular setoids for :tacn:`rewrite` and :tacn:`setoid_replace` (see
- :ref:`Generalizedrewriting`).
-
- .. tacv:: stepl @term by @tactic
-
- This applies :n:`stepl @term` then applies :token:`tactic` to the second goal.
-
- .. tacv:: stepr @term by @tactic
- :name: stepr
-
- This behaves as :tacn:`stepl` but on the right-hand-side of the binary
- relation. Lemmas are expected to be of the form
- :g:`forall x y z, R x y -> eq y z -> R x z`.
-
- .. cmd:: Declare Right Step @term
-
- Adds :n:`@term` to the database used by :tacn:`stepr`.
-
-
-.. tacn:: change @term
- :name: change
-
- This tactic applies to any goal. It implements the rule ``Conv`` given in
- :ref:`subtyping-rules`. :g:`change U` replaces the current goal `T`
- with `U` providing that `U` is well-formed and that `T` and `U` are
- convertible.
-
- .. exn:: Not convertible.
- :undocumented:
-
- .. tacv:: change @term with @term’
-
- This replaces the occurrences of :n:`@term` by :n:`@term’` in the current goal.
- The term :n:`@term` and :n:`@term’` must be convertible.
-
- .. tacv:: change @term at {+ @natural} with @term’
-
- This replaces the occurrences numbered :n:`{+ @natural}` of :n:`@term` by :n:`@term’`
- in the current goal. The terms :n:`@term` and :n:`@term’` must be convertible.
-
- .. exn:: Too few occurrences.
- :undocumented:
-
- .. tacv:: change @term {? {? at {+ @natural}} with @term} in @ident
-
- This applies the :tacn:`change` tactic not to the goal but to the hypothesis :n:`@ident`.
-
- .. tacv:: now_show @term
-
- This is a synonym of :n:`change @term`. It can be used to
- make some proof steps explicit when refactoring a proof script
- to make it readable.
-
- .. seealso:: :ref:`Performing computations <performingcomputations>`
-
-.. _performingcomputations:
-
-Performing computations
----------------------------
-
-.. insertprodn red_expr pattern_occ
-
-.. prodn::
- red_expr ::= red
- | hnf
- | simpl {? @delta_flag } {? @ref_or_pattern_occ }
- | cbv {? @strategy_flag }
- | cbn {? @strategy_flag }
- | lazy {? @strategy_flag }
- | compute {? @delta_flag }
- | vm_compute {? @ref_or_pattern_occ }
- | native_compute {? @ref_or_pattern_occ }
- | unfold {+, @unfold_occ }
- | fold {+ @one_term }
- | pattern {+, @pattern_occ }
- | @ident
- delta_flag ::= {? - } [ {+ @reference } ]
- strategy_flag ::= {+ @red_flag }
- | @delta_flag
- red_flag ::= beta
- | iota
- | match
- | fix
- | cofix
- | zeta
- | delta {? @delta_flag }
- ref_or_pattern_occ ::= @reference {? at @occs_nums }
- | @one_term {? at @occs_nums }
- occs_nums ::= {+ {| @natural | @ident } }
- | - {| @natural | @ident } {* @int_or_var }
- int_or_var ::= @integer
- | @ident
- unfold_occ ::= @reference {? at @occs_nums }
- pattern_occ ::= @one_term {? at @occs_nums }
-
-This set of tactics implements different specialized usages of the
-tactic :tacn:`change`.
-
-All conversion tactics (including :tacn:`change`) can be parameterized by the
-parts of the goal where the conversion can occur. This is done using
-*goal clauses* which consists in a list of hypotheses and, optionally,
-of a reference to the conclusion of the goal. For defined hypothesis
-it is possible to specify if the conversion should occur on the type
-part, the body part or both (default).
-
-Goal clauses are written after a conversion tactic (tactics :tacn:`set`,
-:tacn:`rewrite`, :tacn:`replace` and :tacn:`autorewrite` also use goal
-clauses) and are introduced by the keyword `in`. If no goal clause is
-provided, the default is to perform the conversion only in the
-conclusion.
-
-The syntax and description of the various goal clauses is the
-following:
-
-+ :n:`in {+ @ident} |-` only in hypotheses :n:`{+ @ident}`
-+ :n:`in {+ @ident} |- *` in hypotheses :n:`{+ @ident}` and in the
- conclusion
-+ :n:`in * |-` in every hypothesis
-+ :n:`in *` (equivalent to in :n:`* |- *`) everywhere
-+ :n:`in (type of @ident) (value of @ident) ... |-` in type part of
- :n:`@ident`, in the value part of :n:`@ident`, etc.
-
-For backward compatibility, the notation :n:`in {+ @ident}` performs
-the conversion in hypotheses :n:`{+ @ident}`.
-
-.. tacn:: cbv {? @strategy_flag }
- lazy {? @strategy_flag }
- :name: cbv; lazy
-
- These parameterized reduction tactics apply to any goal and perform
- the normalization of the goal according to the specified flags. In
- correspondence with the kinds of reduction considered in |Coq| namely
- :math:`\beta` (reduction of functional application), :math:`\delta`
- (unfolding of transparent constants, see :ref:`vernac-controlling-the-reduction-strategies`),
- :math:`\iota` (reduction of
- pattern matching over a constructed term, and unfolding of :g:`fix` and
- :g:`cofix` expressions) and :math:`\zeta` (contraction of local definitions), the
- flags are either ``beta``, ``delta``, ``match``, ``fix``, ``cofix``,
- ``iota`` or ``zeta``. The ``iota`` flag is a shorthand for ``match``, ``fix``
- and ``cofix``. The ``delta`` flag itself can be refined into
- :n:`delta [ {+ @qualid} ]` or :n:`delta - [ {+ @qualid} ]`, restricting in the first
- case the constants to unfold to the constants listed, and restricting in the
- second case the constant to unfold to all but the ones explicitly mentioned.
- Notice that the ``delta`` flag does not apply to variables bound by a let-in
- construction inside the :n:`@term` itself (use here the ``zeta`` flag). In
- any cases, opaque constants are not unfolded (see :ref:`vernac-controlling-the-reduction-strategies`).
-
- Normalization according to the flags is done by first evaluating the
- head of the expression into a *weak-head* normal form, i.e. until the
- evaluation is blocked by a variable (or an opaque constant, or an
- axiom), as e.g. in :g:`x u1 ... un` , or :g:`match x with ... end`, or
- :g:`(fix f x {struct x} := ...) x`, or is a constructed form (a
- :math:`\lambda`-expression, a constructor, a cofixpoint, an inductive type, a
- product type, a sort), or is a redex that the flags prevent to reduce. Once a
- weak-head normal form is obtained, subterms are recursively reduced using the
- same strategy.
-
- Reduction to weak-head normal form can be done using two strategies:
- *lazy* (``lazy`` tactic), or *call-by-value* (``cbv`` tactic). The lazy
- strategy is a call-by-need strategy, with sharing of reductions: the
- arguments of a function call are weakly evaluated only when necessary,
- and if an argument is used several times then it is weakly computed
- only once. This reduction is efficient for reducing expressions with
- dead code. For instance, the proofs of a proposition :g:`exists x. P(x)`
- reduce to a pair of a witness :g:`t`, and a proof that :g:`t` satisfies the
- predicate :g:`P`. Most of the time, :g:`t` may be computed without computing
- the proof of :g:`P(t)`, thanks to the lazy strategy.
-
- The call-by-value strategy is the one used in ML languages: the
- arguments of a function call are systematically weakly evaluated
- first. Despite the lazy strategy always performs fewer reductions than
- the call-by-value strategy, the latter is generally more efficient for
- evaluating purely computational expressions (i.e. with little dead code).
-
-.. tacv:: compute
- cbv
- :name: compute; _
-
- These are synonyms for ``cbv beta delta iota zeta``.
-
-.. tacv:: lazy
-
- This is a synonym for ``lazy beta delta iota zeta``.
-
-.. tacv:: compute [ {+ @qualid} ]
- cbv [ {+ @qualid} ]
-
- These are synonyms of :n:`cbv beta delta {+ @qualid} iota zeta`.
-
-.. tacv:: compute - [ {+ @qualid} ]
- cbv - [ {+ @qualid} ]
-
- These are synonyms of :n:`cbv beta delta -{+ @qualid} iota zeta`.
-
-.. tacv:: lazy [ {+ @qualid} ]
- lazy - [ {+ @qualid} ]
-
- These are respectively synonyms of :n:`lazy beta delta {+ @qualid} iota zeta`
- and :n:`lazy beta delta -{+ @qualid} iota zeta`.
-
-.. tacv:: vm_compute
- :name: vm_compute
-
- This tactic evaluates the goal using the optimized call-by-value evaluation
- bytecode-based virtual machine described in :cite:`CompiledStrongReduction`.
- This algorithm is dramatically more efficient than the algorithm used for the
- :tacn:`cbv` tactic, but it cannot be fine-tuned. It is especially interesting for
- full evaluation of algebraic objects. This includes the case of
- reflection-based tactics.
-
-.. tacv:: native_compute
- :name: native_compute
-
- This tactic evaluates the goal by compilation to |OCaml| as described
- in :cite:`FullReduction`. If |Coq| is running in native code, it can be
- typically two to five times faster than :tacn:`vm_compute`. Note however that the
- compilation cost is higher, so it is worth using only for intensive
- computations.
-
- .. flag:: NativeCompute Timing
-
- This flag causes all calls to the native compiler to print
- timing information for the conversion to native code,
- compilation, execution, and reification phases of native
- compilation. Timing is printed in units of seconds of
- wall-clock time.
-
- .. flag:: NativeCompute Profiling
-
- On Linux, if you have the ``perf`` profiler installed, this flag makes
- it possible to profile :tacn:`native_compute` evaluations.
-
- .. opt:: NativeCompute Profile Filename @string
- :name: NativeCompute Profile Filename
-
- This option specifies the profile output; the default is
- ``native_compute_profile.data``. The actual filename used
- will contain extra characters to avoid overwriting an existing file; that
- filename is reported to the user.
- That means you can individually profile multiple uses of
- :tacn:`native_compute` in a script. From the Linux command line, run ``perf report``
- on the profile file to see the results. Consult the ``perf`` documentation
- for more details.
-
-.. flag:: Debug Cbv
-
- This flag makes :tacn:`cbv` (and its derivative :tacn:`compute`) print
- information about the constants it encounters and the unfolding decisions it
- makes.
-
-.. tacn:: red
- :name: red
-
- This tactic applies to a goal that has the form::
-
- forall (x:T1) ... (xk:Tk), T
-
- with :g:`T` :math:`\beta`:math:`\iota`:math:`\zeta`-reducing to :g:`c t`:sub:`1` :g:`... t`:sub:`n` and :g:`c` a
- constant. If :g:`c` is transparent then it replaces :g:`c` with its
- definition (say :g:`t`) and then reduces
- :g:`(t t`:sub:`1` :g:`... t`:sub:`n` :g:`)` according to :math:`\beta`:math:`\iota`:math:`\zeta`-reduction rules.
-
-.. exn:: Not reducible.
- :undocumented:
-
-.. exn:: No head constant to reduce.
- :undocumented:
-
-.. tacn:: hnf
- :name: hnf
-
- This tactic applies to any goal. It replaces the current goal with its
- head normal form according to the :math:`\beta`:math:`\delta`:math:`\iota`:math:`\zeta`-reduction rules, i.e. it
- reduces the head of the goal until it becomes a product or an
- irreducible term. All inner :math:`\beta`:math:`\iota`-redexes are also reduced.
- The behavior of both :tacn:`hnf` can be tuned using the :cmd:`Arguments` command.
-
- Example: The term :g:`fun n : nat => S n + S n` is not reduced by :n:`hnf`.
-
-.. note::
- The :math:`\delta` rule only applies to transparent constants (see :ref:`vernac-controlling-the-reduction-strategies`
- on transparency and opacity).
-
-.. tacn:: cbn
- simpl
- :name: cbn; simpl
-
- These tactics apply to any goal. They try to reduce a term to
- something still readable instead of fully normalizing it. They perform
- a sort of strong normalization with two key differences:
-
- + They unfold a constant if and only if it leads to a :math:`\iota`-reduction,
- i.e. reducing a match or unfolding a fixpoint.
- + While reducing a constant unfolding to (co)fixpoints, the tactics
- use the name of the constant the (co)fixpoint comes from instead of
- the (co)fixpoint definition in recursive calls.
-
- The :tacn:`cbn` tactic is claimed to be a more principled, faster and more
- predictable replacement for :tacn:`simpl`.
-
- The :tacn:`cbn` tactic accepts the same flags as :tacn:`cbv` and
- :tacn:`lazy`. The behavior of both :tacn:`simpl` and :tacn:`cbn`
- can be tuned using the :cmd:`Arguments` command.
-
- .. todo add "See <subsection about controlling the behavior of reduction strategies>"
- to TBA section
-
- Notice that only transparent constants whose name can be reused in the
- recursive calls are possibly unfolded by :tacn:`simpl`. For instance a
- constant defined by :g:`plus' := plus` is possibly unfolded and reused in
- the recursive calls, but a constant such as :g:`succ := plus (S O)` is
- never unfolded. This is the main difference between :tacn:`simpl` and :tacn:`cbn`.
- The tactic :tacn:`cbn` reduces whenever it will be able to reuse it or not:
- :g:`succ t` is reduced to :g:`S t`.
-
-.. tacv:: cbn [ {+ @qualid} ]
- cbn - [ {+ @qualid} ]
-
- These are respectively synonyms of :n:`cbn beta delta [ {+ @qualid} ] iota zeta`
- and :n:`cbn beta delta - [ {+ @qualid} ] iota zeta` (see :tacn:`cbn`).
-
-.. tacv:: simpl @pattern
-
- This applies :tacn:`simpl` only to the subterms matching
- :n:`@pattern` in the current goal.
-
-.. tacv:: simpl @pattern at {+ @natural}
-
- This applies :tacn:`simpl` only to the :n:`{+ @natural}` occurrences of the subterms
- matching :n:`@pattern` in the current goal.
-
- .. exn:: Too few occurrences.
- :undocumented:
-
-.. tacv:: simpl @qualid
- simpl @string
-
- This applies :tacn:`simpl` only to the applicative subterms whose head occurrence
- is the unfoldable constant :n:`@qualid` (the constant can be referred to by
- its notation using :n:`@string` if such a notation exists).
-
-.. tacv:: simpl @qualid at {+ @natural}
- simpl @string at {+ @natural}
-
- This applies :tacn:`simpl` only to the :n:`{+ @natural}` applicative subterms whose
- head occurrence is :n:`@qualid` (or :n:`@string`).
-
-.. flag:: Debug RAKAM
-
- This flag makes :tacn:`cbn` print various debugging information.
- ``RAKAM`` is the Refolding Algebraic Krivine Abstract Machine.
-
-.. tacn:: unfold @qualid
- :name: unfold
-
- This tactic applies to any goal. The argument qualid must denote a
- defined transparent constant or local definition (see
- :ref:`gallina-definitions` and
- :ref:`vernac-controlling-the-reduction-strategies`). The tactic
- :tacn:`unfold` applies the :math:`\delta` rule to each occurrence
- of the constant to which :n:`@qualid` refers in the current goal
- and then replaces it with its :math:`\beta\iota\zeta`-normal form.
- Use the general reduction tactics if you want to avoid this final
- reduction, for instance :n:`cbv delta [@qualid]`.
-
- .. exn:: Cannot coerce @qualid to an evaluable reference.
-
- This error is frequent when trying to unfold something that has
- defined as an inductive type (or constructor) and not as a
- definition.
-
- .. example::
-
- .. coqtop:: abort all fail
-
- Goal 0 <= 1.
- unfold le.
-
- This error can also be raised if you are trying to unfold
- something that has been marked as opaque.
-
- .. example::
-
- .. coqtop:: abort all fail
-
- Opaque Nat.add.
- Goal 1 + 0 = 1.
- unfold Nat.add.
-
- .. tacv:: unfold @qualid in @goal_occurrences
-
- Replaces :n:`@qualid` in hypothesis (or hypotheses) designated
- by :token:`goal_occurrences` with its definition and replaces
- the hypothesis with its :math:`\beta`:math:`\iota` normal form.
-
- .. tacv:: unfold {+, @qualid}
-
- Replaces :n:`{+, @qualid}` with their definitions and replaces
- the current goal with its :math:`\beta`:math:`\iota` normal
- form.
-
- .. tacv:: unfold {+, @qualid at @occurrences }
-
- The list :token:`occurrences` specify the occurrences of
- :n:`@qualid` to be unfolded. Occurrences are located from left
- to right.
-
- .. exn:: Bad occurrence number of @qualid.
- :undocumented:
-
- .. exn:: @qualid does not occur.
- :undocumented:
-
- .. tacv:: unfold @string
-
- If :n:`@string` denotes the discriminating symbol of a notation
- (e.g. "+") or an expression defining a notation (e.g. `"_ +
- _"`), and this notation denotes an application whose head symbol
- is an unfoldable constant, then the tactic unfolds it.
-
- .. tacv:: unfold @string%@ident
-
- This is variant of :n:`unfold @string` where :n:`@string` gets
- its interpretation from the scope bound to the delimiting key
- :token:`ident` instead of its default interpretation (see
- :ref:`Localinterpretationrulesfornotations`).
-
- .. tacv:: unfold {+, {| @qualid | @string{? %@ident } } {? at @occurrences } } {? in @goal_occurrences }
-
- This is the most general form.
-
-.. tacn:: fold @term
- :name: fold
-
- This tactic applies to any goal. The term :n:`@term` is reduced using the
- :tacn:`red` tactic. Every occurrence of the resulting :n:`@term` in the goal is
- then replaced by :n:`@term`. This tactic is particularly useful when a fixpoint
- definition has been wrongfully unfolded, making the goal very hard to read.
- On the other hand, when an unfolded function applied to its argument has been
- reduced, the :tacn:`fold` tactic won't do anything.
-
- .. example::
-
- .. coqtop:: all abort
-
- Goal ~0=0.
- unfold not.
- Fail progress fold not.
- pattern (0 = 0).
- fold not.
-
- .. tacv:: fold {+ @term}
-
- Equivalent to :n:`fold @term ; ... ; fold @term`.
-
-.. tacn:: pattern @term
- :name: pattern
-
- This command applies to any goal. The argument :n:`@term` must be a free
- subterm of the current goal. The command pattern performs :math:`\beta`-expansion
- (the inverse of :math:`\beta`-reduction) of the current goal (say :g:`T`) by
-
- + replacing all occurrences of :n:`@term` in :g:`T` with a fresh variable
- + abstracting this variable
- + applying the abstracted goal to :n:`@term`
-
- For instance, if the current goal :g:`T` is expressible as
- :math:`\varphi`:g:`(t)` where the notation captures all the instances of :g:`t`
- in :math:`\varphi`:g:`(t)`, then :n:`pattern t` transforms it into
- :g:`(fun x:A =>` :math:`\varphi`:g:`(x)) t`. This tactic can be used, for
- instance, when the tactic ``apply`` fails on matching.
-
-.. tacv:: pattern @term at {+ @natural}
-
- Only the occurrences :n:`{+ @natural}` of :n:`@term` are considered for
- :math:`\beta`-expansion. Occurrences are located from left to right.
-
-.. tacv:: pattern @term at - {+ @natural}
-
- All occurrences except the occurrences of indexes :n:`{+ @natural }`
- of :n:`@term` are considered for :math:`\beta`-expansion. Occurrences are located from
- left to right.
-
-.. tacv:: pattern {+, @term}
-
- Starting from a goal :math:`\varphi`:g:`(t`:sub:`1` :g:`... t`:sub:`m`:g:`)`,
- the tactic :n:`pattern t`:sub:`1`:n:`, ..., t`:sub:`m` generates the
- equivalent goal
- :g:`(fun (x`:sub:`1`:g:`:A`:sub:`1`:g:`) ... (x`:sub:`m` :g:`:A`:sub:`m` :g:`) =>`:math:`\varphi`:g:`(x`:sub:`1` :g:`... x`:sub:`m` :g:`)) t`:sub:`1` :g:`... t`:sub:`m`.
- If :g:`t`:sub:`i` occurs in one of the generated types :g:`A`:sub:`j` these
- occurrences will also be considered and possibly abstracted.
-
-.. tacv:: pattern {+, @term at {+ @natural}}
-
- This behaves as above but processing only the occurrences :n:`{+ @natural}` of
- :n:`@term` starting from :n:`@term`.
-
-.. tacv:: pattern {+, @term {? at {? -} {+, @natural}}}
-
- This is the most general syntax that combines the different variants.
-
-.. tacn:: with_strategy @strategy_level_or_var [ {+ @reference } ] @ltac_expr3
- :name: with_strategy
-
- Executes :token:`ltac_expr3`, applying the alternate unfolding
- behavior that the :cmd:`Strategy` command controls, but only for
- :token:`ltac_expr3`. This can be useful for guarding calls to
- reduction in tactic automation to ensure that certain constants are
- never unfolded by tactics like :tacn:`simpl` and :tacn:`cbn` or to
- ensure that unfolding does not fail.
-
- .. example::
-
- .. coqtop:: all reset abort
-
- Opaque id.
- Goal id 10 = 10.
- Fail unfold id.
- with_strategy transparent [id] unfold id.
-
- .. warning::
-
- Use this tactic with care, as effects do not persist past the
- end of the proof script. Notably, this fine-tuning of the
- conversion strategy is not in effect during :cmd:`Qed` nor
- :cmd:`Defined`, so this tactic is most useful either in
- combination with :tacn:`abstract`, which will check the proof
- early while the fine-tuning is still in effect, or to guard
- calls to conversion in tactic automation to ensure that, e.g.,
- :tacn:`unfold` does not fail just because the user made a
- constant :cmd:`Opaque`.
-
- This can be illustrated with the following example involving the
- factorial function.
-
- .. coqtop:: in reset
-
- Fixpoint fact (n : nat) : nat :=
- match n with
- | 0 => 1
- | S n' => n * fact n'
- end.
-
- Suppose now that, for whatever reason, we want in general to
- unfold the :g:`id` function very late during conversion:
-
- .. coqtop:: in
-
- Strategy 1000 [id].
-
- If we try to prove :g:`id (fact n) = fact n` by
- :tacn:`reflexivity`, it will now take time proportional to
- :math:`n!`, because |Coq| will keep unfolding :g:`fact` and
- :g:`*` and :g:`+` before it unfolds :g:`id`, resulting in a full
- computation of :g:`fact n` (in unary, because we are using
- :g:`nat`), which takes time :math:`n!`. We can see this cross
- the relevant threshold at around :math:`n = 9`:
-
- .. coqtop:: all abort
-
- Goal True.
- Time assert (id (fact 8) = fact 8) by reflexivity.
- Time assert (id (fact 9) = fact 9) by reflexivity.
-
- Note that behavior will be the same if you mark :g:`id` as
- :g:`Opaque` because while most reduction tactics refuse to
- unfold :g:`Opaque` constants, conversion treats :g:`Opaque` as
- merely a hint to unfold this constant last.
-
- We can get around this issue by using :tacn:`with_strategy`:
-
- .. coqtop:: all
-
- Goal True.
- Fail Timeout 1 assert (id (fact 100) = fact 100) by reflexivity.
- Time assert (id (fact 100) = fact 100) by with_strategy -1 [id] reflexivity.
-
- However, when we go to close the proof, we will run into
- trouble, because the reduction strategy changes are local to the
- tactic passed to :tacn:`with_strategy`.
-
- .. coqtop:: all abort fail
-
- exact I.
- Timeout 1 Defined.
-
- We can fix this issue by using :tacn:`abstract`:
-
- .. coqtop:: all
-
- Goal True.
- Time assert (id (fact 100) = fact 100) by with_strategy -1 [id] abstract reflexivity.
- exact I.
- Time Defined.
-
- On small examples this sort of behavior doesn't matter, but
- because |Coq| is a super-linear performance domain in so many
- places, unless great care is taken, tactic automation using
- :tacn:`with_strategy` may not be robustly performant when
- scaling the size of the input.
-
- .. warning::
-
- In much the same way this tactic does not play well with
- :cmd:`Qed` and :cmd:`Defined` without using :tacn:`abstract` as
- an intermediary, this tactic does not play well with ``coqchk``,
- even when used with :tacn:`abstract`, due to the inability of
- tactics to persist information about conversion hints in the
- proof term. See `#12200
- <https://github.com/coq/coq/issues/12200>`_ for more details.
-
-Conversion tactics applied to hypotheses
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. tacn:: @tactic in {+, @ident}
-
- Applies :token:`tactic` (any of the conversion tactics listed in this
- section) to the hypotheses :n:`{+ @ident}`.
-
- If :token:`ident` is a local definition, then :token:`ident` can be replaced by
- :n:`type of @ident` to address not the body but the type of the local
- definition.
-
- Example: :n:`unfold not in (type of H1) (type of H3)`.
-
-.. exn:: No such hypothesis: @ident.
- :undocumented:
-
-
-.. _automation:
-
-Automation
-----------
-
-.. tacn:: auto
- :name: auto
-
- This tactic implements a Prolog-like resolution procedure to solve the
- current goal. It first tries to solve the goal using the :tacn:`assumption`
- tactic, then it reduces the goal to an atomic one using :tacn:`intros` and
- introduces the newly generated hypotheses as hints. Then it looks at
- the list of tactics associated to the head symbol of the goal and
- tries to apply one of them (starting from the tactics with lower
- cost). This process is recursively applied to the generated subgoals.
-
- By default, :tacn:`auto` only uses the hypotheses of the current goal and
- the hints of the database named ``core``.
-
- .. warning::
-
- :tacn:`auto` uses a weaker version of :tacn:`apply` that is closer to
- :tacn:`simple apply` so it is expected that sometimes :tacn:`auto` will
- fail even if applying manually one of the hints would succeed.
-
- .. tacv:: auto @natural
-
- Forces the search depth to be :token:`natural`. The maximal search depth
- is 5 by default.
-
- .. tacv:: auto with {+ @ident}
-
- Uses the hint databases :n:`{+ @ident}` in addition to the database ``core``.
-
- .. note::
-
- Use the fake database `nocore` if you want to *not* use the `core`
- database.
-
- .. tacv:: auto with *
-
- Uses all existing hint databases. Using this variant is highly discouraged
- in finished scripts since it is both slower and less robust than the variant
- where the required databases are explicitly listed.
-
- .. seealso::
- :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>` for the list of
- pre-defined databases and the way to create or extend a database.
-
- .. tacv:: auto using {+ @qualid__i} {? with {+ @ident } }
-
- Uses lemmas :n:`@qualid__i` in addition to hints. If :n:`@qualid` is an
- inductive type, it is the collection of its constructors which are added
- as hints.
-
- .. note::
-
- The hints passed through the `using` clause are used in the same
- way as if they were passed through a hint database. Consequently,
- they use a weaker version of :tacn:`apply` and :n:`auto using @qualid`
- may fail where :n:`apply @qualid` succeeds.
-
- Given that this can be seen as counter-intuitive, it could be useful
- to have an option to use full-blown :tacn:`apply` for lemmas passed
- through the `using` clause. Contributions welcome!
-
- .. tacv:: info_auto
-
- Behaves like :tacn:`auto` but shows the tactics it uses to solve the goal. This
- variant is very useful for getting a better understanding of automation, or
- to know what lemmas/assumptions were used.
-
- .. tacv:: debug auto
- :name: debug auto
-
- Behaves like :tacn:`auto` but shows the tactics it tries to solve the goal,
- including failing paths.
-
- .. tacv:: {? info_}auto {? @natural} {? using {+ @qualid}} {? with {+ @ident}}
-
- This is the most general form, combining the various options.
-
-.. tacv:: trivial
- :name: trivial
-
- This tactic is a restriction of :tacn:`auto` that is not recursive
- and tries only hints that cost `0`. Typically it solves trivial
- equalities like :g:`X=X`.
-
- .. tacv:: trivial with {+ @ident}
- trivial with *
- trivial using {+ @qualid}
- debug trivial
- info_trivial
- {? info_}trivial {? using {+ @qualid}} {? with {+ @ident}}
- :name: _; _; _; debug trivial; info_trivial; _
- :undocumented:
-
-.. note::
- :tacn:`auto` and :tacn:`trivial` either solve completely the goal or
- else succeed without changing the goal. Use :g:`solve [ auto ]` and
- :g:`solve [ trivial ]` if you would prefer these tactics to fail when
- they do not manage to solve the goal.
-
-.. flag:: Info Auto
- Debug Auto
- Info Trivial
- Debug Trivial
-
- These flags enable printing of informative or debug information for
- the :tacn:`auto` and :tacn:`trivial` tactics.
-
-.. tacn:: eauto
- :name: eauto
-
- This tactic generalizes :tacn:`auto`. While :tacn:`auto` does not try
- resolution hints which would leave existential variables in the goal,
- :tacn:`eauto` does try them (informally speaking, it internally uses a tactic
- close to :tacn:`simple eapply` instead of a tactic close to :tacn:`simple apply`
- in the case of :tacn:`auto`). As a consequence, :tacn:`eauto`
- can solve such a goal:
-
- .. example::
-
- .. coqtop:: all
-
- Hint Resolve ex_intro : core.
- Goal forall P:nat -> Prop, P 0 -> exists n, P n.
- eauto.
-
- Note that ``ex_intro`` should be declared as a hint.
-
-
- .. tacv:: {? info_}eauto {? @natural} {? using {+ @qualid}} {? with {+ @ident}}
-
- The various options for :tacn:`eauto` are the same as for :tacn:`auto`.
-
- :tacn:`eauto` also obeys the following flags:
-
- .. flag:: Info Eauto
- Debug Eauto
- :undocumented:
-
- .. seealso:: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
-
-
-.. tacn:: autounfold with {+ @ident}
- :name: autounfold
-
- This tactic unfolds constants that were declared through a :cmd:`Hint Unfold`
- in the given databases.
-
-.. tacv:: autounfold with {+ @ident} in @goal_occurrences
-
- Performs the unfolding in the given clause (:token:`goal_occurrences`).
-
-.. tacv:: autounfold with *
-
- Uses the unfold hints declared in all the hint databases.
-
-.. tacn:: autorewrite with {+ @ident}
- :name: autorewrite
-
- This tactic carries out rewritings according to the rewriting rule
- bases :n:`{+ @ident}`.
-
- Each rewriting rule from the base :n:`@ident` is applied to the main subgoal until
- it fails. Once all the rules have been processed, if the main subgoal has
- progressed (e.g., if it is distinct from the initial main goal) then the rules
- of this base are processed again. If the main subgoal has not progressed then
- the next base is processed. For the bases, the behavior is exactly similar to
- the processing of the rewriting rules.
-
- The rewriting rule bases are built with the :cmd:`Hint Rewrite`
- command.
-
-.. warning::
-
- This tactic may loop if you build non terminating rewriting systems.
-
-.. tacv:: autorewrite with {+ @ident} using @tactic
-
- Performs, in the same way, all the rewritings of the bases :n:`{+ @ident}`
- applying tactic to the main subgoal after each rewriting step.
-
-.. tacv:: autorewrite with {+ @ident} in @qualid
-
- Performs all the rewritings in hypothesis :n:`@qualid`.
-
-.. tacv:: autorewrite with {+ @ident} in @qualid using @tactic
-
- Performs all the rewritings in hypothesis :n:`@qualid` applying :n:`@tactic`
- to the main subgoal after each rewriting step.
-
-.. tacv:: autorewrite with {+ @ident} in @goal_occurrences
-
- Performs all the rewriting in the clause :n:`@goal_occurrences`.
-
-.. seealso::
-
- :ref:`Hint-Rewrite <hintrewrite>` for feeding the database of lemmas used by
- :tacn:`autorewrite` and :tacn:`autorewrite` for examples showing the use of this tactic.
-
-.. tacn:: easy
- :name: easy
-
- This tactic tries to solve the current goal by a number of standard closing steps.
- In particular, it tries to close the current goal using the closing tactics
- :tacn:`trivial`, :tacn:`reflexivity`, :tacn:`symmetry`, :tacn:`contradiction`
- and :tacn:`inversion` of hypothesis.
- If this fails, it tries introducing variables and splitting and-hypotheses,
- using the closing tactics afterwards, and splitting the goal using
- :tacn:`split` and recursing.
-
- This tactic solves goals that belong to many common classes; in particular, many cases of
- unsatisfiable hypotheses, and simple equality goals are usually solved by this tactic.
-
-.. tacv:: now @tactic
- :name: now
-
- Run :n:`@tactic` followed by :tacn:`easy`. This is a notation for :n:`@tactic; easy`.
-
-Controlling automation
---------------------------
-
-.. _thehintsdatabasesforautoandeauto:
-
-The hints databases for auto and eauto
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The hints for :tacn:`auto` and :tacn:`eauto` are stored in databases. Each database
-maps head symbols to a list of hints.
-
-.. cmd:: Print Hint @ident
-
- Use this command
- to display the hints associated to the head symbol :n:`@ident`
- (see :ref:`Print Hint <printhint>`). Each hint has a cost that is a nonnegative
- integer, and an optional pattern. The hints with lower cost are tried first. A
- hint is tried by :tacn:`auto` when the conclusion of the current goal matches its
- pattern or when it has no pattern.
-
-Creating Hint databases
-```````````````````````
-
-One can optionally declare a hint database using the command
-:cmd:`Create HintDb`. If a hint is added to an unknown database, it will be
-automatically created.
-
-.. cmd:: Create HintDb @ident {? discriminated}
-
- This command creates a new database named :n:`@ident`. The database is
- implemented by a Discrimination Tree (DT) that serves as an index of
- all the lemmas. The DT can use transparency information to decide if a
- constant should be indexed or not
- (c.f. :ref:`The hints databases for auto and eauto <thehintsdatabasesforautoandeauto>`),
- making the retrieval more efficient. The legacy implementation (the default one
- for new databases) uses the DT only on goals without existentials (i.e., :tacn:`auto`
- goals), for non-Immediate hints and does not make use of transparency
- hints, putting more work on the unification that is run after
- retrieval (it keeps a list of the lemmas in case the DT is not used).
- The new implementation enabled by the discriminated option makes use
- of DTs in all cases and takes transparency information into account.
- However, the order in which hints are retrieved from the DT may differ
- from the order in which they were inserted, making this implementation
- observationally different from the legacy one.
-
-.. cmd:: Hint @hint_definition : {+ @ident}
-
- The general command to add a hint to some databases :n:`{+ @ident}`.
-
- This command supports the :attr:`local`, :attr:`global` and :attr:`export`
- locality attributes. When no locality is explictly given, the
- command is :attr:`local` inside a section and :attr:`global` otherwise.
-
- + :attr:`local` hints are never visible from other modules, even if they
- require or import the current module. Inside a section, the :attr:`local`
- attribute is useless since hints do not survive anyway to the closure of
- sections.
-
- + :attr:`export` are visible from other modules when they import the current
- module. Requiring it is not enough. This attribute is only effective for
- the :cmd:`Hint Resolve`, :cmd:`Hint Immediate`, :cmd:`Hint Unfold` and
- :cmd:`Hint Extern` variants of the command.
-
- + :attr:`global` hints are made available by merely requiring the current
- module.
-
- The various possible :production:`hint_definition`\s are given below.
-
- .. cmdv:: Hint @hint_definition
-
- No database name is given: the hint is registered in the ``core`` database.
-
- .. deprecated:: 8.10
-
- .. cmdv:: Hint Resolve @qualid {? | {? @natural} {? @pattern}} : @ident
- :name: Hint Resolve
-
- This command adds :n:`simple apply @qualid` to the hint list with the head
- symbol of the type of :n:`@qualid`. The cost of that hint is the number of
- subgoals generated by :n:`simple apply @qualid` or :n:`@natural` if specified. The
- associated :n:`@pattern` is inferred from the conclusion of the type of
- :n:`@qualid` or the given :n:`@pattern` if specified. In case the inferred type
- of :n:`@qualid` does not start with a product the tactic added in the hint list
- is :n:`exact @qualid`. In case this type can however be reduced to a type
- starting with a product, the tactic :n:`simple apply @qualid` is also stored in
- the hints list. If the inferred type of :n:`@qualid` contains a dependent
- quantification on a variable which occurs only in the premisses of the type
- and not in its conclusion, no instance could be inferred for the variable by
- unification with the goal. In this case, the hint is added to the hint list
- of :tacn:`eauto` instead of the hint list of auto and a warning is printed. A
- typical example of a hint that is used only by :tacn:`eauto` is a transitivity
- lemma.
-
- .. exn:: @qualid cannot be used as a hint
-
- The head symbol of the type of :n:`@qualid` is a bound variable
- such that this tactic cannot be associated to a constant.
-
- .. cmdv:: Hint Resolve {+ @qualid} : @ident
-
- Adds each :n:`Hint Resolve @qualid`.
-
- .. cmdv:: Hint Resolve -> @qualid : @ident
-
- Adds the left-to-right implication of an equivalence as a hint (informally
- the hint will be used as :n:`apply <- @qualid`, although as mentioned
- before, the tactic actually used is a restricted version of
- :tacn:`apply`).
-
- .. cmdv:: Hint Resolve <- @qualid
-
- Adds the right-to-left implication of an equivalence as a hint.
-
- .. cmdv:: Hint Immediate @qualid : @ident
- :name: Hint Immediate
-
- This command adds :n:`simple apply @qualid; trivial` to the hint list associated
- with the head symbol of the type of :n:`@ident` in the given database. This
- tactic will fail if all the subgoals generated by :n:`simple apply @qualid` are
- not solved immediately by the :tacn:`trivial` tactic (which only tries tactics
- with cost 0).This command is useful for theorems such as the symmetry of
- equality or :g:`n+1=m+1 -> n=m` that we may like to introduce with a limited
- use in order to avoid useless proof-search. The cost of this tactic (which
- never generates subgoals) is always 1, so that it is not used by :tacn:`trivial`
- itself.
-
- .. exn:: @qualid cannot be used as a hint
- :undocumented:
-
- .. cmdv:: Hint Immediate {+ @qualid} : @ident
-
- Adds each :n:`Hint Immediate @qualid`.
-
- .. cmdv:: Hint Constructors @qualid : @ident
- :name: Hint Constructors
-
- If :token:`qualid` is an inductive type, this command adds all its constructors as
- hints of type ``Resolve``. Then, when the conclusion of current goal has the form
- :n:`(@qualid ...)`, :tacn:`auto` will try to apply each constructor.
-
- .. exn:: @qualid is not an inductive type
- :undocumented:
-
- .. cmdv:: Hint Constructors {+ @qualid} : @ident
-
- Extends the previous command for several inductive types.
-
- .. cmdv:: Hint Unfold @qualid : @ident
- :name: Hint Unfold
-
- This adds the tactic :n:`unfold @qualid` to the hint list that will only be
- used when the head constant of the goal is :token:`qualid`.
- Its cost is 4.
-
- .. cmdv:: Hint Unfold {+ @qualid}
-
- Extends the previous command for several defined constants.
-
- .. cmdv:: Hint Transparent {+ @qualid} : @ident
- Hint Opaque {+ @qualid} : @ident
- :name: Hint Transparent; Hint Opaque
-
- This adds transparency hints to the database, making :n:`@qualid`
- transparent or opaque constants during resolution. This information is used
- during unification of the goal with any lemma in the database and inside the
- discrimination network to relax or constrain it in the case of discriminated
- databases.
-
- .. cmdv:: Hint Variables {| Transparent | Opaque } : @ident
- Hint Constants {| Transparent | Opaque } : @ident
- :name: Hint Variables; Hint Constants
-
- This sets the transparency flag used during unification of
- hints in the database for all constants or all variables,
- overwriting the existing settings of opacity. It is advised
- to use this just after a :cmd:`Create HintDb` command.
-
- .. cmdv:: Hint Extern @natural {? @pattern} => @tactic : @ident
- :name: Hint Extern
-
- This hint type is to extend :tacn:`auto` with tactics other than :tacn:`apply` and
- :tacn:`unfold`. For that, we must specify a cost, an optional :n:`@pattern` and a
- :n:`@tactic` to execute.
-
- .. example::
-
- .. coqtop:: in
-
- Hint Extern 4 (~(_ = _)) => discriminate : core.
-
- Now, when the head of the goal is a disequality, ``auto`` will try
- discriminate if it does not manage to solve the goal with hints with a
- cost less than 4.
-
- One can even use some sub-patterns of the pattern in
- the tactic script. A sub-pattern is a question mark followed by an
- identifier, like ``?X1`` or ``?X2``. Here is an example:
-
- .. example::
-
- .. coqtop:: reset all
-
- Require Import List.
- Hint Extern 5 ({?X1 = ?X2} + {?X1 <> ?X2}) => generalize X1, X2; decide equality : eqdec.
- Goal forall a b:list (nat * nat), {a = b} + {a <> b}.
- Info 1 auto with eqdec.
-
- .. cmdv:: Hint Cut @regexp : @ident
- :name: Hint Cut
-
- .. warning::
-
- These hints currently only apply to typeclass proof search and the
- :tacn:`typeclasses eauto` tactic.
-
- This command can be used to cut the proof-search tree according to a regular
- expression matching paths to be cut. The grammar for regular expressions is
- the following. Beware, there is no operator precedence during parsing, one can
- check with :cmd:`Print HintDb` to verify the current cut expression:
-
- .. prodn::
- regexp ::= @ident (hint or instance identifier)
- | _ (any hint)
- | @regexp | @regexp (disjunction)
- | @regexp @regexp (sequence)
- | @regexp * (Kleene star)
- | emp (empty)
- | eps (epsilon)
- | ( @regexp )
-
- The `emp` regexp does not match any search path while `eps`
- matches the empty path. During proof search, the path of
- successive successful hints on a search branch is recorded, as a
- list of identifiers for the hints (note that :cmd:`Hint Extern`\’s do not have
- an associated identifier).
- Before applying any hint :n:`@ident` the current path `p` extended with
- :n:`@ident` is matched against the current cut expression `c` associated to
- the hint database. If matching succeeds, the hint is *not* applied. The
- semantics of :n:`Hint Cut @regexp` is to set the cut expression
- to :n:`c | regexp`, the initial cut expression being `emp`.
-
- .. cmdv:: Hint Mode @qualid {* {| + | ! | - } } : @ident
- :name: Hint Mode
-
- This sets an optional mode of use of the identifier :n:`@qualid`. When
- proof-search faces a goal that ends in an application of :n:`@qualid` to
- arguments :n:`@term ... @term`, the mode tells if the hints associated to
- :n:`@qualid` can be applied or not. A mode specification is a list of n ``+``,
- ``!`` or ``-`` items that specify if an argument of the identifier is to be
- treated as an input (``+``), if its head only is an input (``!``) or an output
- (``-``) of the identifier. For a mode to match a list of arguments, input
- terms and input heads *must not* contain existential variables or be
- existential variables respectively, while outputs can be any term. Multiple
- modes can be declared for a single identifier, in that case only one mode
- needs to match the arguments for the hints to be applied. The head of a term
- is understood here as the applicative head, or the match or projection
- scrutinee’s head, recursively, casts being ignored. :cmd:`Hint Mode` is
- especially useful for typeclasses, when one does not want to support default
- instances and avoid ambiguity in general. Setting a parameter of a class as an
- input forces proof-search to be driven by that index of the class, with ``!``
- giving more flexibility by allowing existentials to still appear deeper in the
- index but not at its head.
-
- .. note::
-
- + One can use a :cmd:`Hint Extern` with no pattern to do
- pattern matching on hypotheses using ``match goal with``
- inside the tactic.
-
- + If you want to add hints such as :cmd:`Hint Transparent`,
- :cmd:`Hint Cut`, or :cmd:`Hint Mode`, for typeclass
- resolution, do not forget to put them in the
- ``typeclass_instances`` hint database.
-
-
-Hint databases defined in the |Coq| standard library
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Several hint databases are defined in the |Coq| standard library. The
-actual content of a database is the collection of hints declared
-to belong to this database in each of the various modules currently
-loaded. Especially, requiring new modules may extend the database.
-At |Coq| startup, only the core database is nonempty and can be used.
-
-:core: This special database is automatically used by ``auto``, except when
- pseudo-database ``nocore`` is given to ``auto``. The core database
- contains only basic lemmas about negation, conjunction, and so on.
- Most of the hints in this database come from the Init and Logic directories.
-
-:arith: This database contains all lemmas about Peano’s arithmetic proved in the
- directories Init and Arith.
-
-:zarith: contains lemmas about binary signed integers from the
- directories theories/ZArith. The database also contains
- high-cost hints that call :tacn:`lia` on equations and
- inequalities in ``nat`` or ``Z``.
-
-:bool: contains lemmas about booleans, mostly from directory theories/Bool.
-
-:datatypes: is for lemmas about lists, streams and so on that are mainly proved
- in the Lists subdirectory.
-
-:sets: contains lemmas about sets and relations from the directories Sets and
- Relations.
-
-:typeclass_instances: contains all the typeclass instances declared in the
- environment, including those used for ``setoid_rewrite``,
- from the Classes directory.
-
-:fset: internal database for the implementation of the ``FSets`` library.
-
-:ordered_type: lemmas about ordered types (as defined in the legacy ``OrderedType`` module),
- mainly used in the ``FSets`` and ``FMaps`` libraries.
-
-You are advised not to put your own hints in the core database, but
-use one or several databases specific to your development.
-
-.. _removehints:
-
-.. cmd:: Remove Hints {+ @term} : {+ @ident}
-
- This command removes the hints associated to terms :n:`{+ @term}` in databases
- :n:`{+ @ident}`.
-
-.. _printhint:
-
-.. cmd:: Print Hint
-
- This command displays all hints that apply to the current goal. It
- fails if no proof is being edited, while the two variants can be used
- at every moment.
-
-**Variants:**
-
-
-.. cmd:: Print Hint @ident
-
- This command displays only tactics associated with :n:`@ident` in the hints
- list. This is independent of the goal being edited, so this command will not
- fail if no goal is being edited.
-
-.. cmd:: Print Hint *
-
- This command displays all declared hints.
-
-.. cmd:: Print HintDb @ident
-
- This command displays all hints from database :n:`@ident`.
-
-.. _hintrewrite:
-
-.. cmd:: Hint Rewrite {+ @term} : {+ @ident}
-
- This vernacular command adds the terms :n:`{+ @term}` (their types must be
- equalities) in the rewriting bases :n:`{+ @ident}` with the default orientation
- (left to right). Notice that the rewriting bases are distinct from the :tacn:`auto`
- hint bases and that :tacn:`auto` does not take them into account.
-
- This command is synchronous with the section mechanism (see :ref:`section-mechanism`):
- when closing a section, all aliases created by ``Hint Rewrite`` in that
- section are lost. Conversely, when loading a module, all ``Hint Rewrite``
- declarations at the global level of that module are loaded.
-
-**Variants:**
-
-.. cmd:: Hint Rewrite -> {+ @term} : {+ @ident}
-
- This is strictly equivalent to the command above (we only make explicit the
- orientation which otherwise defaults to ->).
-
-.. cmd:: Hint Rewrite <- {+ @term} : {+ @ident}
-
- Adds the rewriting rules :n:`{+ @term}` with a right-to-left orientation in
- the bases :n:`{+ @ident}`.
-
-.. cmd:: Hint Rewrite {? {| -> | <- } } {+ @one_term } {? using @ltac_expr } {? : {* @ident } }
-
- When the rewriting rules :n:`{+ @term}` in :n:`{+ @ident}` will be used, the
- tactic ``tactic`` will be applied to the generated subgoals, the main subgoal
- excluded.
-
-.. cmd:: Print Rewrite HintDb @ident
-
- This command displays all rewrite hints contained in :n:`@ident`.
-
-Hint locality
-~~~~~~~~~~~~~
-
-Hints provided by the ``Hint`` commands are erased when closing a section.
-Conversely, all hints of a module ``A`` that are not defined inside a
-section (and not defined with option ``Local``) become available when the
-module ``A`` is required (using e.g. ``Require A.``).
-
-As of today, hints only have a binary behavior regarding locality, as
-described above: either they disappear at the end of a section scope,
-or they remain global forever. This causes a scalability issue,
-because hints coming from an unrelated part of the code may badly
-influence another development. It can be mitigated to some extent
-thanks to the :cmd:`Remove Hints` command,
-but this is a mere workaround and has some limitations (for instance, external
-hints cannot be removed).
-
-A proper way to fix this issue is to bind the hints to their module scope, as
-for most of the other objects |Coq| uses. Hints should only be made available when
-the module they are defined in is imported, not just required. It is very
-difficult to change the historical behavior, as it would break a lot of scripts.
-We propose a smooth transitional path by providing the :opt:`Loose Hint Behavior`
-option which accepts three flags allowing for a fine-grained handling of
-non-imported hints.
-
-.. opt:: Loose Hint Behavior {| "Lax" | "Warn" | "Strict" }
- :name: Loose Hint Behavior
-
- This option accepts three values, which control the behavior of hints w.r.t.
- :cmd:`Import`:
-
- - "Lax": this is the default, and corresponds to the historical behavior,
- that is, hints defined outside of a section have a global scope.
-
- - "Warn": outputs a warning when a non-imported hint is used. Note that this
- is an over-approximation, because a hint may be triggered by a run that
- will eventually fail and backtrack, resulting in the hint not being
- actually useful for the proof.
-
- - "Strict": changes the behavior of an unloaded hint to a immediate fail
- tactic, allowing to emulate an import-scoped hint mechanism.
-
-.. _tactics-implicit-automation:
-
-Setting implicit automation tactics
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. cmd:: Proof with @tactic
-
- This command may be used to start a proof. It defines a default tactic
- to be used each time a tactic command ``tactic``:sub:`1` is ended by ``...``.
- In this case the tactic command typed by the user is equivalent to
- ``tactic``:sub:`1` ``;tactic``.
-
- .. seealso:: :cmd:`Proof` in :ref:`proof-editing-mode`.
-
-
- .. cmdv:: Proof with @tactic using {+ @ident}
-
- Combines in a single line ``Proof with`` and ``Proof using``, see :ref:`proof-editing-mode`
-
- .. cmdv:: Proof using {+ @ident} with @tactic
-
- Combines in a single line ``Proof with`` and ``Proof using``, see :ref:`proof-editing-mode`
-
-.. _decisionprocedures:
-
-Decision procedures
--------------------
-
-.. tacn:: tauto
- :name: tauto
-
- This tactic implements a decision procedure for intuitionistic propositional
- calculus based on the contraction-free sequent calculi LJT* of Roy Dyckhoff
- :cite:`Dyc92`. Note that :tacn:`tauto` succeeds on any instance of an
- intuitionistic tautological proposition. :tacn:`tauto` unfolds negations and
- logical equivalence but does not unfold any other definition.
-
-.. example::
-
- The following goal can be proved by :tacn:`tauto` whereas :tacn:`auto` would
- fail:
-
- .. coqtop:: reset all
-
- Goal forall (x:nat) (P:nat -> Prop), x = 0 \/ P x -> x <> 0 -> P x.
- intros.
- tauto.
-
-Moreover, if it has nothing else to do, :tacn:`tauto` performs introductions.
-Therefore, the use of :tacn:`intros` in the previous proof is unnecessary.
-:tacn:`tauto` can for instance for:
-
-.. example::
-
- .. coqtop:: reset all
-
- Goal forall (A:Prop) (P:nat -> Prop), A \/ (forall x:nat, ~ A -> P x) -> forall x:nat, ~ A -> P x.
- tauto.
-
-.. note::
- In contrast, :tacn:`tauto` cannot solve the following goal
- :g:`Goal forall (A:Prop) (P:nat -> Prop), A \/ (forall x:nat, ~ A -> P x) ->`
- :g:`forall x:nat, ~ ~ (A \/ P x).`
- because :g:`(forall x:nat, ~ A -> P x)` cannot be treated as atomic and
- an instantiation of `x` is necessary.
-
-.. tacv:: dtauto
- :name: dtauto
-
- While :tacn:`tauto` recognizes inductively defined connectives isomorphic to
- the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``,
- ``Empty_set``, ``unit``, ``True``, :tacn:`dtauto` also recognizes all inductive
- types with one constructor and no indices, i.e. record-style connectives.
-
-.. tacn:: intuition @tactic
- :name: intuition
-
- The tactic :tacn:`intuition` takes advantage of the search-tree built by the
- decision procedure involved in the tactic :tacn:`tauto`. It uses this
- information to generate a set of subgoals equivalent to the original one (but
- simpler than it) and applies the tactic :n:`@tactic` to them :cite:`Mun94`. If
- this tactic fails on some goals then :tacn:`intuition` fails. In fact,
- :tacn:`tauto` is simply :g:`intuition fail`.
-
- .. example::
-
- For instance, the tactic :g:`intuition auto` applied to the goal::
-
- (forall (x:nat), P x) /\ B -> (forall (y:nat), P y) /\ P O \/ B /\ P O
-
- internally replaces it by the equivalent one::
-
- (forall (x:nat), P x), B |- P O
-
- and then uses :tacn:`auto` which completes the proof.
-
-Originally due to César Muñoz, these tactics (:tacn:`tauto` and
-:tacn:`intuition`) have been completely re-engineered by David Delahaye using
-mainly the tactic language (see :ref:`ltac`). The code is
-now much shorter and a significant increase in performance has been noticed.
-The general behavior with respect to dependent types, unfolding and
-introductions has slightly changed to get clearer semantics. This may lead to
-some incompatibilities.
-
-.. tacv:: intuition
-
- Is equivalent to :g:`intuition auto with *`.
-
-.. tacv:: dintuition
- :name: dintuition
-
- While :tacn:`intuition` recognizes inductively defined connectives
- isomorphic to the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``,
- ``Empty_set``, ``unit``, ``True``, :tacn:`dintuition` also recognizes all inductive
- types with one constructor and no indices, i.e. record-style connectives.
-
-.. flag:: Intuition Negation Unfolding
-
- Controls whether :tacn:`intuition` unfolds inner negations which do not need
- to be unfolded. This flag is on by default.
-
-.. tacn:: rtauto
- :name: rtauto
-
- The :tacn:`rtauto` tactic solves propositional tautologies similarly to what
- :tacn:`tauto` does. The main difference is that the proof term is built using a
- reflection scheme applied to a sequent calculus proof of the goal. The search
- procedure is also implemented using a different technique.
-
- Users should be aware that this difference may result in faster proof-search
- but slower proof-checking, and :tacn:`rtauto` might not solve goals that
- :tacn:`tauto` would be able to solve (e.g. goals involving universal
- quantifiers).
-
- Note that this tactic is only available after a ``Require Import Rtauto``.
-
-.. tacn:: firstorder
- :name: firstorder
-
- The tactic :tacn:`firstorder` is an experimental extension of :tacn:`tauto` to
- first- order reasoning, written by Pierre Corbineau. It is not restricted to
- usual logical connectives but instead may reason about any first-order class
- inductive definition.
-
-.. opt:: Firstorder Solver @tactic
- :name: Firstorder Solver
-
- The default tactic used by :tacn:`firstorder` when no rule applies is
- :g:`auto with core`, it can be reset locally or globally using this option.
-
- .. cmd:: Print Firstorder Solver
-
- Prints the default tactic used by :tacn:`firstorder` when no rule applies.
-
-.. tacv:: firstorder @tactic
-
- Tries to solve the goal with :n:`@tactic` when no logical rule may apply.
-
-.. tacv:: firstorder using {+ @qualid}
-
- .. deprecated:: 8.3
-
- Use the syntax below instead (with commas).
-
-.. tacv:: firstorder using {+, @qualid}
-
- Adds lemmas :n:`{+, @qualid}` to the proof-search environment. If :n:`@qualid`
- refers to an inductive type, it is the collection of its constructors which are
- added to the proof-search environment.
-
-.. tacv:: firstorder with {+ @ident}
-
- Adds lemmas from :tacn:`auto` hint bases :n:`{+ @ident}` to the proof-search
- environment.
-
-.. tacv:: firstorder @tactic using {+, @qualid} with {+ @ident}
-
- This combines the effects of the different variants of :tacn:`firstorder`.
-
-.. opt:: Firstorder Depth @natural
- :name: Firstorder Depth
-
- This option controls the proof-search depth bound.
-
-.. tacn:: congruence
- :name: congruence
-
- The tactic :tacn:`congruence`, by Pierre Corbineau, implements the standard
- Nelson and Oppen congruence closure algorithm, which is a decision procedure
- for ground equalities with uninterpreted symbols. It also includes
- constructor theory (see :tacn:`injection` and :tacn:`discriminate`). If the goal
- is a non-quantified equality, congruence tries to prove it with non-quantified
- equalities in the context. Otherwise it tries to infer a discriminable equality
- from those in the context. Alternatively, congruence tries to prove that a
- hypothesis is equal to the goal or to the negation of another hypothesis.
-
- :tacn:`congruence` is also able to take advantage of hypotheses stating
- quantified equalities, but you have to provide a bound for the number of extra
- equalities generated that way. Please note that one of the sides of the
- equality must contain all the quantified variables in order for congruence to
- match against it.
-
-.. example::
-
- .. coqtop:: reset all
-
- Theorem T (A:Type) (f:A -> A) (g: A -> A -> A) a b: a=(f a) -> (g b (f a))=(f (f a)) -> (g a b)=(f (g b a)) -> (g a b)=a.
- intros.
- congruence.
- Qed.
-
- Theorem inj (A:Type) (f:A -> A * A) (a c d: A) : f = pair a -> Some (f c) = Some (f d) -> c=d.
- intros.
- congruence.
- Qed.
-
-.. tacv:: congruence @natural
-
- Tries to add at most :token:`natural` instances of hypotheses stating quantified equalities
- to the problem in order to solve it. A bigger value of :token:`natural` does not make
- success slower, only failure. You might consider adding some lemmas as
- hypotheses using assert in order for :tacn:`congruence` to use them.
-
-.. tacv:: congruence with {+ @term}
- :name: congruence with
-
- Adds :n:`{+ @term}` to the pool of terms used by :tacn:`congruence`. This helps
- in case you have partially applied constructors in your goal.
-
-.. exn:: I don’t know how to handle dependent equality.
-
- The decision procedure managed to find a proof of the goal or of a
- discriminable equality but this proof could not be built in |Coq| because of
- dependently-typed functions.
-
-.. exn:: Goal is solvable by congruence but some arguments are missing. Try congruence with {+ @term}, replacing metavariables by arbitrary terms.
-
- The decision procedure could solve the goal with the provision that additional
- arguments are supplied for some partially applied constructors. Any term of an
- appropriate type will allow the tactic to successfully solve the goal. Those
- additional arguments can be given to congruence by filling in the holes in the
- terms given in the error message, using the :tacn:`congruence with` variant described above.
-
-.. flag:: Congruence Verbose
-
- This flag makes :tacn:`congruence` print debug information.
-
Checking properties of terms
----------------------------
@@ -4647,189 +2893,6 @@ using the ``Require Import`` command.
Use :tacn:`classical_right` to prove the right part of the disjunction with
the assumption that the negation of left part holds.
-.. _tactics-automating:
-
-Automating
-------------
-
-
-.. tacn:: btauto
- :name: btauto
-
- The tactic :tacn:`btauto` implements a reflexive solver for boolean
- tautologies. It solves goals of the form :g:`t = u` where `t` and `u` are
- constructed over the following grammar:
-
- .. prodn::
- btauto_term ::= @ident
- | true
- | false
- | orb @btauto_term @btauto_term
- | andb @btauto_term @btauto_term
- | xorb @btauto_term @btauto_term
- | negb @btauto_term
- | if @btauto_term then @btauto_term else @btauto_term
-
- Whenever the formula supplied is not a tautology, it also provides a
- counter-example.
-
- Internally, it uses a system very similar to the one of the ring
- tactic.
-
- Note that this tactic is only available after a ``Require Import Btauto``.
-
- .. exn:: Cannot recognize a boolean equality.
-
- The goal is not of the form :g:`t = u`. Especially note that :tacn:`btauto`
- doesn't introduce variables into the context on its own.
-
-.. tacv:: field
- field_simplify {* @term}
- field_simplify_eq
-
- The field tactic is built on the same ideas as ring: this is a
- reflexive tactic that solves or simplifies equations in a field
- structure. The main idea is to reduce a field expression (which is an
- extension of ring expressions with the inverse and division
- operations) to a fraction made of two polynomial expressions.
-
- Tactic :n:`field` is used to solve subgoals, whereas :n:`field_simplify {+ @term}`
- replaces the provided terms by their reduced fraction.
- :n:`field_simplify_eq` applies when the conclusion is an equation: it
- simplifies both hand sides and multiplies so as to cancel
- denominators. So it produces an equation without division nor inverse.
-
- All of these 3 tactics may generate a subgoal in order to prove that
- denominators are different from zero.
-
- See :ref:`Theringandfieldtacticfamilies` for more information on the tactic and how to
- declare new field structures. All declared field structures can be
- printed with the Print Fields command.
-
-.. example::
-
- .. coqtop:: reset all
-
- Require Import Reals.
- Goal forall x y:R,
- (x * y > 0)%R ->
- (x * (1 / x + x / (x + y)))%R =
- ((- 1 / y) * y * (- x * (x / (x + y)) - 1))%R.
-
- intros; field.
-
-.. seealso::
-
- File plugins/ring/RealField.v for an example of instantiation,
- theory theories/Reals for many examples of use of field.
-
-Non-logical tactics
-------------------------
-
-
-.. tacn:: cycle @integer
- :name: cycle
-
- Reorders the selected goals so that the first :n:`@integer` goals appear after the
- other selected goals.
- If :n:`@integer` is negative, it puts the last :n:`@integer` goals at the
- beginning of the list.
- The tactic is only useful with a goal selector, most commonly `all:`.
- Note that other selectors reorder goals; `1,3: cycle 1` is not equivalent
- to `all: cycle 1`. See :tacn:`… : … (goal selector)`.
-
-.. example::
-
- .. coqtop:: none reset
-
- Parameter P : nat -> Prop.
-
- .. coqtop:: all abort
-
- Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5.
- repeat split.
- all: cycle 2.
- all: cycle -3.
-
-.. tacn:: swap @integer @integer
- :name: swap
-
- Exchanges the position of the specified goals.
- Negative values for :n:`@integer` indicate counting goals
- backward from the end of the list of selected goals. Goals are indexed from 1.
- The tactic is only useful with a goal selector, most commonly `all:`.
- Note that other selectors reorder goals; `1,3: swap 1 3` is not equivalent
- to `all: swap 1 3`. See :tacn:`… : … (goal selector)`.
-
-.. example::
-
- .. coqtop:: all abort
-
- Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5.
- repeat split.
- all: swap 1 3.
- all: swap 1 -1.
-
-.. tacn:: revgoals
- :name: revgoals
-
- Reverses the order of the selected goals. The tactic is only useful with a goal
- selector, most commonly `all :`. Note that other selectors reorder goals;
- `1,3: revgoals` is not equivalent to `all: revgoals`. See :tacn:`… : … (goal selector)`.
-
- .. example::
-
- .. coqtop:: all abort
-
- Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5.
- repeat split.
- all: revgoals.
-
-.. tacn:: shelve
- :name: shelve
-
- This tactic moves all goals under focus to a shelf. While on the
- shelf, goals will not be focused on. They can be solved by
- unification, or they can be called back into focus with the command
- :cmd:`Unshelve`.
-
- .. tacv:: shelve_unifiable
- :name: shelve_unifiable
-
- Shelves only the goals under focus that are mentioned in other goals.
- Goals that appear in the type of other goals can be solved by unification.
-
- .. example::
-
- .. coqtop:: all abort
-
- Goal exists n, n=0.
- refine (ex_intro _ _ _).
- all: shelve_unifiable.
- reflexivity.
-
-.. cmd:: Unshelve
-
- This command moves all the goals on the shelf (see :tacn:`shelve`)
- from the shelf into focus, by appending them to the end of the current
- list of focused goals.
-
-.. tacn:: unshelve @tactic
- :name: unshelve
-
- Performs :n:`@tactic`, then unshelves existential variables added to the
- shelf by the execution of :n:`@tactic`, prepending them to the current goal.
-
-.. tacn:: give_up
- :name: give_up
-
- This tactic removes the focused goals from the proof. They are not
- solved, and cannot be solved later in the proof. As the goals are not
- solved, the proof cannot be closed.
-
- The ``give_up`` tactic can be used while editing a proof, to choose to
- write the proof script in a non-sequential order.
-
Delaying solving unification constraints
----------------------------------------
@@ -4849,14 +2912,14 @@ Proof maintenance
*Experimental.* Many tactics, such as :tacn:`intros`, can automatically generate names, such
as "H0" or "H1" for a new hypothesis introduced from a goal. Subsequent proof steps
-may explicitly refer to these names. However, future versions of |Coq| may not assign
+may explicitly refer to these names. However, future versions of Coq may not assign
names exactly the same way, which could cause the proof to fail because the
new names don't match the explicit references in the proof.
The following "Mangle Names" settings let users find all the
places where proofs rely on automatically generated names, which can
then be named explicitly to avoid any incompatibility. These
-settings cause |Coq| to generate different names, producing errors for
+settings cause Coq to generate different names, producing errors for
references to automatically generated names.
.. flag:: Mangle Names
@@ -4878,7 +2941,7 @@ Performance-oriented tactic variants
For advanced usage. Similar to :tacn:`change` :n:`@term`, but as an optimization,
it skips checking that :n:`@term` is convertible to the goal.
- Recall that the |Coq| kernel typechecks proofs again when they are concluded to
+ Recall that the Coq kernel typechecks proofs again when they are concluded to
ensure safety. Hence, using :tacn:`change` checks convertibility twice
overall, while :tacn:`change_no_check` can produce ill-typed terms,
but checks convertibility only once.
diff --git a/doc/sphinx/proof-engine/vernacular-commands.rst b/doc/sphinx/proof-engine/vernacular-commands.rst
index 301559d69d..86d1d25745 100644
--- a/doc/sphinx/proof-engine/vernacular-commands.rst
+++ b/doc/sphinx/proof-engine/vernacular-commands.rst
@@ -133,7 +133,7 @@ to accessible objects. (see Section :ref:`invocation-of-tactics`).
.. prodn::
search_item ::= {? {| head | hyp | concl | headhyp | headconcl } : } @string {? % @scope_key }
- | {? {| head | hyp | concl | headhyp | headconcl } : } @one_term
+ | {? {| head | hyp | concl | headhyp | headconcl } : } @one_pattern
| is : @logical_kind
Searched objects can be filtered by patterns, by the constants they
@@ -141,9 +141,9 @@ to accessible objects. (see Section :ref:`invocation-of-tactics`).
names.
The location of the pattern or constant within a term
- :n:`@one_term`
+ :n:`@one_pattern`
Search for objects whose type contains a subterm matching the
- pattern :n:`@one_term`. Holes of the pattern are indicated by
+ pattern :n:`@one_pattern`. Holes of the pattern are indicated by
`_` or :n:`?@ident`. If the same :n:`?@ident` occurs more than
once in the pattern, all occurrences in the subterm must be
identical. See :ref:`this example <search-pattern>`.
@@ -312,7 +312,7 @@ to accessible objects. (see Section :ref:`invocation-of-tactics`).
Search is:Instance [ Reflexive | Symmetric ].
-.. cmd:: SearchHead @one_term {? {| inside | outside } {+ @qualid } }
+.. cmd:: SearchHead @one_pattern {? {| inside | outside } {+ @qualid } }
.. deprecated:: 8.12
@@ -320,8 +320,8 @@ to accessible objects. (see Section :ref:`invocation-of-tactics`).
Displays the name and type of all hypotheses of the
selected goal (if any) and theorems of the current context that have the
- form :n:`{? forall {* @binder }, } {* P__i -> } C` where :n:`@one_term`
- matches a subterm of `C` in head position. For example, a :n:`@one_term` of `f _ b`
+ form :n:`{? forall {* @binder }, } {* P__i -> } C` where :n:`@one_pattern`
+ matches a subterm of `C` in head position. For example, a :n:`@one_pattern` of `f _ b`
matches `f a b`, which is a subterm of `C` in head position when `C` is `f a b c`.
See :cmd:`Search` for an explanation of the `inside`/`outside` clauses.
@@ -337,12 +337,12 @@ to accessible objects. (see Section :ref:`invocation-of-tactics`).
SearchHead le.
SearchHead (@eq bool).
-.. cmd:: SearchPattern @one_term {? {| inside | outside } {+ @qualid } }
+.. cmd:: SearchPattern @one_pattern {? {| inside | outside } {+ @qualid } }
Displays the name and type of all hypotheses of the
selected goal (if any) and theorems of the current context
ending with :n:`{? forall {* @binder }, } {* P__i -> } C` that match the pattern
- :n:`@one_term`.
+ :n:`@one_pattern`.
See :cmd:`Search` for an explanation of the `inside`/`outside` clauses.
@@ -362,11 +362,11 @@ to accessible objects. (see Section :ref:`invocation-of-tactics`).
SearchPattern (?X1 + _ = _ + ?X1).
-.. cmd:: SearchRewrite @one_term {? {| inside | outside } {+ @qualid } }
+.. cmd:: SearchRewrite @one_pattern {? {| inside | outside } {+ @qualid } }
Displays the name and type of all hypotheses of the
selected goal (if any) and theorems of the current context that have the form
- :n:`{? forall {* @binder }, } {* P__i -> } LHS = RHS` where :n:`@one_term`
+ :n:`{? forall {* @binder }, } {* P__i -> } LHS = RHS` where :n:`@one_pattern`
matches either `LHS` or `RHS`.
See :cmd:`Search` for an explanation of the `inside`/`outside` clauses.
@@ -433,7 +433,7 @@ Requests to the environment
reference ::= @qualid
| @string {? % @scope_key }
- Displays the full name of objects from |Coq|'s various qualified namespaces such as terms,
+ Displays the full name of objects from Coq's various qualified namespaces such as terms,
modules and Ltac, thereby showing the module they are defined in. It also displays notation definitions.
:n:`@qualid`
@@ -491,7 +491,7 @@ Printing flags
.. flag:: Fast Name Printing
- When turned on, |Coq| uses an asymptotically faster algorithm for the
+ When turned on, Coq uses an asymptotically faster algorithm for the
generation of unambiguous names of bound variables while printing terms.
While faster, it is also less clever and results in a typically less elegant
display, e.g. it will generate more names rather than reusing certain names
@@ -504,12 +504,12 @@ Printing flags
Loading files
-----------------
-|Coq| offers the possibility of loading different parts of a whole
+Coq offers the possibility of loading different parts of a whole
development stored in separate files. Their contents will be loaded as
if they were entered from the keyboard. This means that the loaded
-files are text files containing sequences of commands for |Coq|’s
-toplevel. This kind of file is called a *script* for |Coq|. The standard
-(and default) extension of |Coq|’s script files is .v.
+files are text files containing sequences of commands for Coq’s
+toplevel. This kind of file is called a *script* for Coq. The standard
+(and default) extension of Coq’s script files is .v.
.. cmd:: Load {? Verbose } {| @string | @ident }
@@ -521,7 +521,7 @@ toplevel. This kind of file is called a *script* for |Coq|. The standard
If :n:`@string` is specified, it must specify a complete filename.
`~` and .. abbreviations are
- allowed as well as shell variables. If no extension is specified, |Coq|
+ allowed as well as shell variables. If no extension is specified, Coq
will use the default extension ``.v``.
Files loaded this way can't leave proofs open, nor can :cmd:`Load`
@@ -531,7 +531,7 @@ toplevel. This kind of file is called a *script* for |Coq|. The standard
:cmd:`Require` loads `.vo` files that were previously
compiled from `.v` files.
- :n:`Verbose` displays the |Coq| output for each command and tactic
+ :n:`Verbose` displays the Coq output for each command and tactic
in the loaded file, as if the commands and tactics were entered interactively.
.. exn:: Can’t find file @ident on loadpath.
@@ -556,14 +556,14 @@ file is a particular case of a module called a *library file*.
.. cmd:: Require {? {| Import | Export } } {+ @qualid }
:name: Require; Require Import; Require Export
- Loads compiled modules into the |Coq| environment. For each :n:`@qualid`, which has the form
+ Loads compiled modules into the Coq environment. For each :n:`@qualid`, which has the form
:n:`{* @ident__prefix . } @ident`, the command searches for the logical name represented
by the :n:`@ident__prefix`\s and loads the compiled file :n:`@ident.vo` from the associated
filesystem directory.
The process is applied recursively to all the loaded files;
if they contain :cmd:`Require` commands, those commands are executed as well.
- The compiled files must have been compiled with the same version of |Coq|.
+ The compiled files must have been compiled with the same version of Coq.
The compiled files are neither replayed nor rechecked.
* :n:`Import` - additionally does an :cmd:`Import` on the loaded module, making components defined
@@ -606,15 +606,15 @@ file is a particular case of a module called a *library file*.
The command tried to load library file :n:`@ident`.vo that
depends on some specific version of library :n:`@qualid` which is not the
- one already loaded in the current |Coq| session. Probably :n:`@ident.v` was
+ one already loaded in the current Coq session. Probably :n:`@ident.v` was
not properly recompiled with the last version of the file containing
module :token:`qualid`.
.. exn:: Bad magic number.
The file :n:`@ident.vo` was found but either it is not a
- |Coq| compiled module, or it was compiled with an incompatible
- version of |Coq|.
+ Coq compiled module, or it was compiled with an incompatible
+ version of Coq.
.. exn:: The file @ident.vo contains library @qualid__1 and not library @qualid__2.
@@ -633,15 +633,16 @@ file is a particular case of a module called a *library file*.
.. cmd:: Print Libraries
This command displays the list of library files loaded in the
- current |Coq| session.
+ current Coq session.
.. cmd:: Declare ML Module {+ @string }
- This commands dynamically loads |OCaml| compiled code from
+ This commands dynamically loads OCaml compiled code from
a :n:`.mllib` file.
It is used to load plugins dynamically. The
- files must be accessible in the current |OCaml| loadpath (see the
- command :cmd:`Add ML Path`). The :n:`.mllib` suffix may be omitted.
+ files must be accessible in the current OCaml loadpath (see
+ :ref:`command line option <command-line-options>` :n:`-I` and command :cmd:`Add ML Path`). The
+ :n:`.mllib` suffix may be omitted.
This command is reserved for plugin developers, who should provide
a .v file containing the command. Users of the plugins will then generally
@@ -656,7 +657,7 @@ file is a particular case of a module called a *library file*.
.. cmd:: Print ML Modules
- This prints the name of all |OCaml| modules loaded with :cmd:`Declare ML Module`.
+ This prints the name of all OCaml modules loaded with :cmd:`Declare ML Module`.
To know from where these module were loaded, the user
should use the command :cmd:`Locate File`.
@@ -666,7 +667,7 @@ file is a particular case of a module called a *library file*.
Loadpath
------------
-Loadpaths are preferably managed using |Coq| command line options (see
+Loadpaths are preferably managed using Coq command line options (see
Section :ref:`libraries-and-filesystem`) but there remain vernacular commands to manage them
for practical purposes. Such commands are only meant to be issued in
the toplevel, and using them in source files is discouraged.
@@ -703,33 +704,35 @@ the toplevel, and using them in source files is discouraged.
This command is equivalent to the command line option
:n:`-R @string @dirpath`. It adds the physical directory string and all its
- subdirectories to the current |Coq| loadpath.
+ subdirectories to the current Coq loadpath.
.. cmd:: Remove LoadPath @string
- This command removes the path :n:`@string` from the current |Coq| loadpath.
+ This command removes the path :n:`@string` from the current Coq loadpath.
.. cmd:: Print LoadPath {? @dirpath }
- This command displays the current |Coq| loadpath. If :n:`@dirpath` is specified,
+ This command displays the current Coq loadpath. If :n:`@dirpath` is specified,
displays only the paths that extend that prefix.
.. cmd:: Add ML Path @string
- This command adds the path :n:`@string` to the current |OCaml|
- loadpath (cf. :cmd:`Declare ML Module`).
-
+ Equivalent to the :ref:`command line option <command-line-options>`
+ :n:`-I @string`. Adds the path :n:`@string` to the current OCaml
+ loadpath (cf. :cmd:`Declare ML Module`). It is for
+ convenience, such as for use in an interactive session, and it
+ is not exported to compiled files. For separation of concerns with
+ respect to the relocability of files, we recommend using
+ :n:`-I @string`.
.. cmd:: Print ML Path
- This command displays the current |OCaml| loadpath. This
- command makes sense only under the bytecode version of ``coqtop``, i.e.
- using option ``-byte``
- (cf. :cmd:`Declare ML Module`).
-
+ Displays the current OCaml loadpath, as provided by
+ the :ref:`command line option <command-line-options>` :n:`-I @string` or by the command :cmd:`Add
+ ML Path` `@string` (cf. :cmd:`Declare ML Module`).
.. _backtracking_subsection:
@@ -789,25 +792,25 @@ Quitting and debugging
.. cmd:: Quit
- Causes |Coq| to exit. Valid only in coqtop.
+ Causes Coq to exit. Valid only in coqtop.
.. cmd:: Drop
- This command temporarily enters the |OCaml| toplevel.
- It is a debug facility used by |Coq|’s implementers. Valid only in the
+ This command temporarily enters the OCaml toplevel.
+ It is a debug facility used by Coq’s implementers. Valid only in the
bytecode version of coqtop.
- The |OCaml| command:
+ The OCaml command:
::
#use "include";;
adds the right loadpaths and loads some toplevel printers for all
- abstract types of |Coq|- section_path, identifiers, terms, judgments, ….
+ abstract types of Coq- section_path, identifiers, terms, judgments, ….
You can also use the file base_include instead, that loads only the
pretty-printers for section_paths and identifiers. You can return back
- to |Coq| with the command:
+ to Coq with the command:
::
@@ -815,9 +818,9 @@ Quitting and debugging
.. warning::
- #. It only works with the bytecode version of |Coq| (i.e. `coqtop.byte`,
+ #. It only works with the bytecode version of Coq (i.e. `coqtop.byte`,
see Section `interactive-use`).
- #. You must have compiled |Coq| from the source package and set the
+ #. You must have compiled Coq from the source package and set the
environment variable COQTOP to the root of your copy of the sources
(see Section `customization-by-environment-variables`).
@@ -961,7 +964,7 @@ Controlling the reduction strategies and the conversion algorithm
----------------------------------------------------------------------
-|Coq| provides reduction strategies that the tactics can invoke and two
+Coq provides reduction strategies that the tactics can invoke and two
different algorithms to check the convertibility of types. The first
conversion algorithm lazily compares applicative terms while the other
is a brute-force but efficient algorithm that first normalizes the
@@ -985,16 +988,11 @@ described first.
constants in the :n:`@reference` sequence in tactics using δ-conversion (unfolding
a constant is replacing it by its definition).
- :cmd:`Opaque` has also an effect on the conversion algorithm of |Coq|, telling
- it to delay the unfolding of a constant as much as possible when |Coq|
+ :cmd:`Opaque` has also an effect on the conversion algorithm of Coq, telling
+ it to delay the unfolding of a constant as much as possible when Coq
has to check the conversion (see Section :ref:`conversion-rules`) of two distinct
applied constants.
- .. seealso::
-
- Sections :ref:`performingcomputations`, :ref:`tactics-automating`,
- :ref:`proof-editing-mode`
-
.. cmd:: Transparent {+ @reference }
This command accepts the :attr:`global` attribute. By default, the scope
@@ -1015,10 +1013,7 @@ described first.
There is no constant named :n:`@qualid` in the environment.
- .. seealso::
-
- Sections :ref:`performingcomputations`,
- :ref:`tactics-automating`, :ref:`proof-editing-mode`
+.. seealso:: :ref:`performingcomputations` and :ref:`proof-editing-mode`
.. _vernac-strategy:
@@ -1230,15 +1225,15 @@ in support libraries of plug-ins.
.. _exposing-constants-to-ocaml-libraries:
-Exposing constants to |OCaml| libraries
+Exposing constants to OCaml libraries
```````````````````````````````````````
.. cmd:: Register @qualid__1 as @qualid__2
- Makes the constant :n:`@qualid__1` accessible to |OCaml| libraries under
+ Makes the constant :n:`@qualid__1` accessible to OCaml libraries under
the name :n:`@qualid__2`. The constant can then be dynamically located
- in |OCaml| code by
- calling :n:`Coqlib.lib_ref "@qualid__2"`. The |OCaml| code doesn't need
+ in OCaml code by
+ calling :n:`Coqlib.lib_ref "@qualid__2"`. The OCaml code doesn't need
to know where the constant is defined (what file, module, library, etc.).
As a special case, when the first segment of :n:`@qualid__2` is :g:`kernel`,
@@ -1267,9 +1262,9 @@ Registering primitive operations
.. cmd:: Primitive @ident_decl {? : @term } := #@ident
- Makes the primitive type or primitive operator :n:`#@ident` defined in |OCaml|
- accessible in |Coq| commands and tactics.
- For internal use by implementors of |Coq|'s standard library or standard library
+ Makes the primitive type or primitive operator :n:`#@ident` defined in OCaml
+ accessible in Coq commands and tactics.
+ For internal use by implementors of Coq's standard library or standard library
replacements. No space is allowed after the `#`. Invalid values give a syntax
error.
diff --git a/doc/sphinx/proofs/automatic-tactics/auto.rst b/doc/sphinx/proofs/automatic-tactics/auto.rst
new file mode 100644
index 0000000000..e6dc6f6c51
--- /dev/null
+++ b/doc/sphinx/proofs/automatic-tactics/auto.rst
@@ -0,0 +1,672 @@
+.. _automation:
+
+=========================
+Programmable proof search
+=========================
+
+.. tacn:: auto
+ :name: auto
+
+ This tactic implements a Prolog-like resolution procedure to solve the
+ current goal. It first tries to solve the goal using the :tacn:`assumption`
+ tactic, then it reduces the goal to an atomic one using :tacn:`intros` and
+ introduces the newly generated hypotheses as hints. Then it looks at
+ the list of tactics associated to the head symbol of the goal and
+ tries to apply one of them (starting from the tactics with lower
+ cost). This process is recursively applied to the generated subgoals.
+
+ By default, :tacn:`auto` only uses the hypotheses of the current goal and
+ the hints of the database named ``core``.
+
+ .. warning::
+
+ :tacn:`auto` uses a weaker version of :tacn:`apply` that is closer to
+ :tacn:`simple apply` so it is expected that sometimes :tacn:`auto` will
+ fail even if applying manually one of the hints would succeed.
+
+ .. tacv:: auto @natural
+
+ Forces the search depth to be :token:`natural`. The maximal search depth
+ is 5 by default.
+
+ .. tacv:: auto with {+ @ident}
+
+ Uses the hint databases :n:`{+ @ident}` in addition to the database ``core``.
+
+ .. note::
+
+ Use the fake database `nocore` if you want to *not* use the `core`
+ database.
+
+ .. tacv:: auto with *
+
+ Uses all existing hint databases. Using this variant is highly discouraged
+ in finished scripts since it is both slower and less robust than the variant
+ where the required databases are explicitly listed.
+
+ .. seealso::
+ :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>` for the list of
+ pre-defined databases and the way to create or extend a database.
+
+ .. tacv:: auto using {+ @qualid__i} {? with {+ @ident } }
+
+ Uses lemmas :n:`@qualid__i` in addition to hints. If :n:`@qualid` is an
+ inductive type, it is the collection of its constructors which are added
+ as hints.
+
+ .. note::
+
+ The hints passed through the `using` clause are used in the same
+ way as if they were passed through a hint database. Consequently,
+ they use a weaker version of :tacn:`apply` and :n:`auto using @qualid`
+ may fail where :n:`apply @qualid` succeeds.
+
+ Given that this can be seen as counter-intuitive, it could be useful
+ to have an option to use full-blown :tacn:`apply` for lemmas passed
+ through the `using` clause. Contributions welcome!
+
+ .. tacv:: info_auto
+
+ Behaves like :tacn:`auto` but shows the tactics it uses to solve the goal. This
+ variant is very useful for getting a better understanding of automation, or
+ to know what lemmas/assumptions were used.
+
+ .. tacv:: debug auto
+ :name: debug auto
+
+ Behaves like :tacn:`auto` but shows the tactics it tries to solve the goal,
+ including failing paths.
+
+ .. tacv:: {? info_}auto {? @natural} {? using {+ @qualid}} {? with {+ @ident}}
+
+ This is the most general form, combining the various options.
+
+.. tacv:: trivial
+ :name: trivial
+
+ This tactic is a restriction of :tacn:`auto` that is not recursive
+ and tries only hints that cost `0`. Typically it solves trivial
+ equalities like :g:`X=X`.
+
+ .. tacv:: trivial with {+ @ident}
+ trivial with *
+ trivial using {+ @qualid}
+ debug trivial
+ info_trivial
+ {? info_}trivial {? using {+ @qualid}} {? with {+ @ident}}
+ :name: _; _; _; debug trivial; info_trivial; _
+ :undocumented:
+
+.. note::
+ :tacn:`auto` and :tacn:`trivial` either solve completely the goal or
+ else succeed without changing the goal. Use :g:`solve [ auto ]` and
+ :g:`solve [ trivial ]` if you would prefer these tactics to fail when
+ they do not manage to solve the goal.
+
+.. flag:: Info Auto
+ Debug Auto
+ Info Trivial
+ Debug Trivial
+
+ These flags enable printing of informative or debug information for
+ the :tacn:`auto` and :tacn:`trivial` tactics.
+
+.. tacn:: eauto
+ :name: eauto
+
+ This tactic generalizes :tacn:`auto`. While :tacn:`auto` does not try
+ resolution hints which would leave existential variables in the goal,
+ :tacn:`eauto` does try them (informally speaking, it internally uses a tactic
+ close to :tacn:`simple eapply` instead of a tactic close to :tacn:`simple apply`
+ in the case of :tacn:`auto`). As a consequence, :tacn:`eauto`
+ can solve such a goal:
+
+ .. example::
+
+ .. coqtop:: all
+
+ Hint Resolve ex_intro : core.
+ Goal forall P:nat -> Prop, P 0 -> exists n, P n.
+ eauto.
+
+ Note that ``ex_intro`` should be declared as a hint.
+
+
+ .. tacv:: {? info_}eauto {? @natural} {? using {+ @qualid}} {? with {+ @ident}}
+
+ The various options for :tacn:`eauto` are the same as for :tacn:`auto`.
+
+ :tacn:`eauto` also obeys the following flags:
+
+ .. flag:: Info Eauto
+ Debug Eauto
+ :undocumented:
+
+ .. seealso:: :ref:`The Hints Databases for auto and eauto <thehintsdatabasesforautoandeauto>`
+
+
+.. tacn:: autounfold with {+ @ident}
+ :name: autounfold
+
+ This tactic unfolds constants that were declared through a :cmd:`Hint Unfold`
+ in the given databases.
+
+.. tacv:: autounfold with {+ @ident} in @goal_occurrences
+
+ Performs the unfolding in the given clause (:token:`goal_occurrences`).
+
+.. tacv:: autounfold with *
+
+ Uses the unfold hints declared in all the hint databases.
+
+.. tacn:: autorewrite with {+ @ident}
+ :name: autorewrite
+
+ This tactic carries out rewritings according to the rewriting rule
+ bases :n:`{+ @ident}`.
+
+ Each rewriting rule from the base :n:`@ident` is applied to the main subgoal until
+ it fails. Once all the rules have been processed, if the main subgoal has
+ progressed (e.g., if it is distinct from the initial main goal) then the rules
+ of this base are processed again. If the main subgoal has not progressed then
+ the next base is processed. For the bases, the behavior is exactly similar to
+ the processing of the rewriting rules.
+
+ The rewriting rule bases are built with the :cmd:`Hint Rewrite`
+ command.
+
+.. warning::
+
+ This tactic may loop if you build non terminating rewriting systems.
+
+.. tacv:: autorewrite with {+ @ident} using @tactic
+
+ Performs, in the same way, all the rewritings of the bases :n:`{+ @ident}`
+ applying tactic to the main subgoal after each rewriting step.
+
+.. tacv:: autorewrite with {+ @ident} in @qualid
+
+ Performs all the rewritings in hypothesis :n:`@qualid`.
+
+.. tacv:: autorewrite with {+ @ident} in @qualid using @tactic
+
+ Performs all the rewritings in hypothesis :n:`@qualid` applying :n:`@tactic`
+ to the main subgoal after each rewriting step.
+
+.. tacv:: autorewrite with {+ @ident} in @goal_occurrences
+
+ Performs all the rewriting in the clause :n:`@goal_occurrences`.
+
+.. seealso::
+
+ :ref:`Hint-Rewrite <hintrewrite>` for feeding the database of lemmas used by
+ :tacn:`autorewrite` and :tacn:`autorewrite` for examples showing the use of this tactic.
+
+.. tacn:: easy
+ :name: easy
+
+ This tactic tries to solve the current goal by a number of standard closing steps.
+ In particular, it tries to close the current goal using the closing tactics
+ :tacn:`trivial`, :tacn:`reflexivity`, :tacn:`symmetry`, :tacn:`contradiction`
+ and :tacn:`inversion` of hypothesis.
+ If this fails, it tries introducing variables and splitting and-hypotheses,
+ using the closing tactics afterwards, and splitting the goal using
+ :tacn:`split` and recursing.
+
+ This tactic solves goals that belong to many common classes; in particular, many cases of
+ unsatisfiable hypotheses, and simple equality goals are usually solved by this tactic.
+
+.. tacv:: now @tactic
+ :name: now
+
+ Run :n:`@tactic` followed by :tacn:`easy`. This is a notation for :n:`@tactic; easy`.
+
+Controlling automation
+--------------------------
+
+.. _thehintsdatabasesforautoandeauto:
+
+The hints databases for auto and eauto
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The hints for :tacn:`auto` and :tacn:`eauto` are stored in databases. Each database
+maps head symbols to a list of hints.
+
+.. cmd:: Print Hint @ident
+
+ Use this command
+ to display the hints associated to the head symbol :n:`@ident`
+ (see :ref:`Print Hint <printhint>`). Each hint has a cost that is a nonnegative
+ integer, and an optional pattern. The hints with lower cost are tried first. A
+ hint is tried by :tacn:`auto` when the conclusion of the current goal matches its
+ pattern or when it has no pattern.
+
+Creating Hint databases
+```````````````````````
+
+One can optionally declare a hint database using the command
+:cmd:`Create HintDb`. If a hint is added to an unknown database, it will be
+automatically created.
+
+.. cmd:: Create HintDb @ident {? discriminated}
+
+ This command creates a new database named :n:`@ident`. The database is
+ implemented by a Discrimination Tree (DT) that serves as an index of
+ all the lemmas. The DT can use transparency information to decide if a
+ constant should be indexed or not
+ (c.f. :ref:`The hints databases for auto and eauto <thehintsdatabasesforautoandeauto>`),
+ making the retrieval more efficient. The legacy implementation (the default one
+ for new databases) uses the DT only on goals without existentials (i.e., :tacn:`auto`
+ goals), for non-Immediate hints and does not make use of transparency
+ hints, putting more work on the unification that is run after
+ retrieval (it keeps a list of the lemmas in case the DT is not used).
+ The new implementation enabled by the discriminated option makes use
+ of DTs in all cases and takes transparency information into account.
+ However, the order in which hints are retrieved from the DT may differ
+ from the order in which they were inserted, making this implementation
+ observationally different from the legacy one.
+
+.. cmd:: Hint @hint_definition : {+ @ident}
+
+ The general command to add a hint to some databases :n:`{+ @ident}`.
+
+ This command supports the :attr:`local`, :attr:`global` and :attr:`export`
+ locality attributes. When no locality is explictly given, the
+ command is :attr:`local` inside a section and :attr:`global` otherwise.
+
+ + :attr:`local` hints are never visible from other modules, even if they
+ require or import the current module. Inside a section, the :attr:`local`
+ attribute is useless since hints do not survive anyway to the closure of
+ sections.
+
+ + :attr:`export` are visible from other modules when they import the current
+ module. Requiring it is not enough. This attribute is only effective for
+ the :cmd:`Hint Resolve`, :cmd:`Hint Immediate`, :cmd:`Hint Unfold` and
+ :cmd:`Hint Extern` variants of the command.
+
+ + :attr:`global` hints are made available by merely requiring the current
+ module.
+
+ The various possible :production:`hint_definition`\s are given below.
+
+ .. cmdv:: Hint @hint_definition
+
+ No database name is given: the hint is registered in the ``core`` database.
+
+ .. deprecated:: 8.10
+
+ .. cmdv:: Hint Resolve @qualid {? | {? @natural} {? @pattern}} : @ident
+ :name: Hint Resolve
+
+ This command adds :n:`simple apply @qualid` to the hint list with the head
+ symbol of the type of :n:`@qualid`. The cost of that hint is the number of
+ subgoals generated by :n:`simple apply @qualid` or :n:`@natural` if specified. The
+ associated :n:`@pattern` is inferred from the conclusion of the type of
+ :n:`@qualid` or the given :n:`@pattern` if specified. In case the inferred type
+ of :n:`@qualid` does not start with a product the tactic added in the hint list
+ is :n:`exact @qualid`. In case this type can however be reduced to a type
+ starting with a product, the tactic :n:`simple apply @qualid` is also stored in
+ the hints list. If the inferred type of :n:`@qualid` contains a dependent
+ quantification on a variable which occurs only in the premisses of the type
+ and not in its conclusion, no instance could be inferred for the variable by
+ unification with the goal. In this case, the hint is added to the hint list
+ of :tacn:`eauto` instead of the hint list of auto and a warning is printed. A
+ typical example of a hint that is used only by :tacn:`eauto` is a transitivity
+ lemma.
+
+ .. exn:: @qualid cannot be used as a hint
+
+ The head symbol of the type of :n:`@qualid` is a bound variable
+ such that this tactic cannot be associated to a constant.
+
+ .. cmdv:: Hint Resolve {+ @qualid} : @ident
+
+ Adds each :n:`Hint Resolve @qualid`.
+
+ .. cmdv:: Hint Resolve -> @qualid : @ident
+
+ Adds the left-to-right implication of an equivalence as a hint (informally
+ the hint will be used as :n:`apply <- @qualid`, although as mentioned
+ before, the tactic actually used is a restricted version of
+ :tacn:`apply`).
+
+ .. cmdv:: Hint Resolve <- @qualid
+
+ Adds the right-to-left implication of an equivalence as a hint.
+
+ .. cmdv:: Hint Immediate @qualid : @ident
+ :name: Hint Immediate
+
+ This command adds :n:`simple apply @qualid; trivial` to the hint list associated
+ with the head symbol of the type of :n:`@ident` in the given database. This
+ tactic will fail if all the subgoals generated by :n:`simple apply @qualid` are
+ not solved immediately by the :tacn:`trivial` tactic (which only tries tactics
+ with cost 0).This command is useful for theorems such as the symmetry of
+ equality or :g:`n+1=m+1 -> n=m` that we may like to introduce with a limited
+ use in order to avoid useless proof-search. The cost of this tactic (which
+ never generates subgoals) is always 1, so that it is not used by :tacn:`trivial`
+ itself.
+
+ .. exn:: @qualid cannot be used as a hint
+ :undocumented:
+
+ .. cmdv:: Hint Immediate {+ @qualid} : @ident
+
+ Adds each :n:`Hint Immediate @qualid`.
+
+ .. cmdv:: Hint Constructors @qualid : @ident
+ :name: Hint Constructors
+
+ If :token:`qualid` is an inductive type, this command adds all its constructors as
+ hints of type ``Resolve``. Then, when the conclusion of current goal has the form
+ :n:`(@qualid ...)`, :tacn:`auto` will try to apply each constructor.
+
+ .. exn:: @qualid is not an inductive type
+ :undocumented:
+
+ .. cmdv:: Hint Constructors {+ @qualid} : @ident
+
+ Extends the previous command for several inductive types.
+
+ .. cmdv:: Hint Unfold @qualid : @ident
+ :name: Hint Unfold
+
+ This adds the tactic :n:`unfold @qualid` to the hint list that will only be
+ used when the head constant of the goal is :token:`qualid`.
+ Its cost is 4.
+
+ .. cmdv:: Hint Unfold {+ @qualid}
+
+ Extends the previous command for several defined constants.
+
+ .. cmdv:: Hint Transparent {+ @qualid} : @ident
+ Hint Opaque {+ @qualid} : @ident
+ :name: Hint Transparent; Hint Opaque
+
+ This adds transparency hints to the database, making :n:`@qualid`
+ transparent or opaque constants during resolution. This information is used
+ during unification of the goal with any lemma in the database and inside the
+ discrimination network to relax or constrain it in the case of discriminated
+ databases.
+
+ .. cmdv:: Hint Variables {| Transparent | Opaque } : @ident
+ Hint Constants {| Transparent | Opaque } : @ident
+ :name: Hint Variables; Hint Constants
+
+ This sets the transparency flag used during unification of
+ hints in the database for all constants or all variables,
+ overwriting the existing settings of opacity. It is advised
+ to use this just after a :cmd:`Create HintDb` command.
+
+ .. cmdv:: Hint Extern @natural {? @pattern} => @tactic : @ident
+ :name: Hint Extern
+
+ This hint type is to extend :tacn:`auto` with tactics other than :tacn:`apply` and
+ :tacn:`unfold`. For that, we must specify a cost, an optional :n:`@pattern` and a
+ :n:`@tactic` to execute.
+
+ .. example::
+
+ .. coqtop:: in
+
+ Hint Extern 4 (~(_ = _)) => discriminate : core.
+
+ Now, when the head of the goal is a disequality, ``auto`` will try
+ discriminate if it does not manage to solve the goal with hints with a
+ cost less than 4.
+
+ One can even use some sub-patterns of the pattern in
+ the tactic script. A sub-pattern is a question mark followed by an
+ identifier, like ``?X1`` or ``?X2``. Here is an example:
+
+ .. example::
+
+ .. coqtop:: reset all
+
+ Require Import List.
+ Hint Extern 5 ({?X1 = ?X2} + {?X1 <> ?X2}) => generalize X1, X2; decide equality : eqdec.
+ Goal forall a b:list (nat * nat), {a = b} + {a <> b}.
+ Info 1 auto with eqdec.
+
+ .. cmdv:: Hint Cut @regexp : @ident
+ :name: Hint Cut
+
+ .. warning::
+
+ These hints currently only apply to typeclass proof search and the
+ :tacn:`typeclasses eauto` tactic.
+
+ This command can be used to cut the proof-search tree according to a regular
+ expression matching paths to be cut. The grammar for regular expressions is
+ the following. Beware, there is no operator precedence during parsing, one can
+ check with :cmd:`Print HintDb` to verify the current cut expression:
+
+ .. prodn::
+ regexp ::= @ident (hint or instance identifier)
+ | _ (any hint)
+ | @regexp | @regexp (disjunction)
+ | @regexp @regexp (sequence)
+ | @regexp * (Kleene star)
+ | emp (empty)
+ | eps (epsilon)
+ | ( @regexp )
+
+ The `emp` regexp does not match any search path while `eps`
+ matches the empty path. During proof search, the path of
+ successive successful hints on a search branch is recorded, as a
+ list of identifiers for the hints (note that :cmd:`Hint Extern`\’s do not have
+ an associated identifier).
+ Before applying any hint :n:`@ident` the current path `p` extended with
+ :n:`@ident` is matched against the current cut expression `c` associated to
+ the hint database. If matching succeeds, the hint is *not* applied. The
+ semantics of :n:`Hint Cut @regexp` is to set the cut expression
+ to :n:`c | regexp`, the initial cut expression being `emp`.
+
+ .. cmdv:: Hint Mode @qualid {* {| + | ! | - } } : @ident
+ :name: Hint Mode
+
+ This sets an optional mode of use of the identifier :n:`@qualid`. When
+ proof-search faces a goal that ends in an application of :n:`@qualid` to
+ arguments :n:`@term ... @term`, the mode tells if the hints associated to
+ :n:`@qualid` can be applied or not. A mode specification is a list of n ``+``,
+ ``!`` or ``-`` items that specify if an argument of the identifier is to be
+ treated as an input (``+``), if its head only is an input (``!``) or an output
+ (``-``) of the identifier. For a mode to match a list of arguments, input
+ terms and input heads *must not* contain existential variables or be
+ existential variables respectively, while outputs can be any term. Multiple
+ modes can be declared for a single identifier, in that case only one mode
+ needs to match the arguments for the hints to be applied. The head of a term
+ is understood here as the applicative head, or the match or projection
+ scrutinee’s head, recursively, casts being ignored. :cmd:`Hint Mode` is
+ especially useful for typeclasses, when one does not want to support default
+ instances and avoid ambiguity in general. Setting a parameter of a class as an
+ input forces proof-search to be driven by that index of the class, with ``!``
+ giving more flexibility by allowing existentials to still appear deeper in the
+ index but not at its head.
+
+ .. note::
+
+ + One can use a :cmd:`Hint Extern` with no pattern to do
+ pattern matching on hypotheses using ``match goal with``
+ inside the tactic.
+
+ + If you want to add hints such as :cmd:`Hint Transparent`,
+ :cmd:`Hint Cut`, or :cmd:`Hint Mode`, for typeclass
+ resolution, do not forget to put them in the
+ ``typeclass_instances`` hint database.
+
+
+Hint databases defined in the Coq standard library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Several hint databases are defined in the Coq standard library. The
+actual content of a database is the collection of hints declared
+to belong to this database in each of the various modules currently
+loaded. Especially, requiring new modules may extend the database.
+At Coq startup, only the core database is nonempty and can be used.
+
+:core: This special database is automatically used by ``auto``, except when
+ pseudo-database ``nocore`` is given to ``auto``. The core database
+ contains only basic lemmas about negation, conjunction, and so on.
+ Most of the hints in this database come from the Init and Logic directories.
+
+:arith: This database contains all lemmas about Peano’s arithmetic proved in the
+ directories Init and Arith.
+
+:zarith: contains lemmas about binary signed integers from the
+ directories theories/ZArith. The database also contains
+ high-cost hints that call :tacn:`lia` on equations and
+ inequalities in ``nat`` or ``Z``.
+
+:bool: contains lemmas about booleans, mostly from directory theories/Bool.
+
+:datatypes: is for lemmas about lists, streams and so on that are mainly proved
+ in the Lists subdirectory.
+
+:sets: contains lemmas about sets and relations from the directories Sets and
+ Relations.
+
+:typeclass_instances: contains all the typeclass instances declared in the
+ environment, including those used for ``setoid_rewrite``,
+ from the Classes directory.
+
+:fset: internal database for the implementation of the ``FSets`` library.
+
+:ordered_type: lemmas about ordered types (as defined in the legacy ``OrderedType`` module),
+ mainly used in the ``FSets`` and ``FMaps`` libraries.
+
+You are advised not to put your own hints in the core database, but
+use one or several databases specific to your development.
+
+.. _removehints:
+
+.. cmd:: Remove Hints {+ @term} : {+ @ident}
+
+ This command removes the hints associated to terms :n:`{+ @term}` in databases
+ :n:`{+ @ident}`.
+
+.. _printhint:
+
+.. cmd:: Print Hint
+
+ This command displays all hints that apply to the current goal. It
+ fails if no proof is being edited, while the two variants can be used
+ at every moment.
+
+**Variants:**
+
+
+.. cmd:: Print Hint @ident
+
+ This command displays only tactics associated with :n:`@ident` in the hints
+ list. This is independent of the goal being edited, so this command will not
+ fail if no goal is being edited.
+
+.. cmd:: Print Hint *
+
+ This command displays all declared hints.
+
+.. cmd:: Print HintDb @ident
+
+ This command displays all hints from database :n:`@ident`.
+
+.. _hintrewrite:
+
+.. cmd:: Hint Rewrite {+ @term} : {+ @ident}
+
+ This vernacular command adds the terms :n:`{+ @term}` (their types must be
+ equalities) in the rewriting bases :n:`{+ @ident}` with the default orientation
+ (left to right). Notice that the rewriting bases are distinct from the :tacn:`auto`
+ hint bases and that :tacn:`auto` does not take them into account.
+
+ This command is synchronous with the section mechanism (see :ref:`section-mechanism`):
+ when closing a section, all aliases created by ``Hint Rewrite`` in that
+ section are lost. Conversely, when loading a module, all ``Hint Rewrite``
+ declarations at the global level of that module are loaded.
+
+**Variants:**
+
+.. cmd:: Hint Rewrite -> {+ @term} : {+ @ident}
+
+ This is strictly equivalent to the command above (we only make explicit the
+ orientation which otherwise defaults to ->).
+
+.. cmd:: Hint Rewrite <- {+ @term} : {+ @ident}
+
+ Adds the rewriting rules :n:`{+ @term}` with a right-to-left orientation in
+ the bases :n:`{+ @ident}`.
+
+.. cmd:: Hint Rewrite {? {| -> | <- } } {+ @one_term } {? using @ltac_expr } {? : {* @ident } }
+
+ When the rewriting rules :n:`{+ @term}` in :n:`{+ @ident}` will be used, the
+ tactic ``tactic`` will be applied to the generated subgoals, the main subgoal
+ excluded.
+
+.. cmd:: Print Rewrite HintDb @ident
+
+ This command displays all rewrite hints contained in :n:`@ident`.
+
+Hint locality
+~~~~~~~~~~~~~
+
+Hints provided by the ``Hint`` commands are erased when closing a section.
+Conversely, all hints of a module ``A`` that are not defined inside a
+section (and not defined with option ``Local``) become available when the
+module ``A`` is required (using e.g. ``Require A.``).
+
+As of today, hints only have a binary behavior regarding locality, as
+described above: either they disappear at the end of a section scope,
+or they remain global forever. This causes a scalability issue,
+because hints coming from an unrelated part of the code may badly
+influence another development. It can be mitigated to some extent
+thanks to the :cmd:`Remove Hints` command,
+but this is a mere workaround and has some limitations (for instance, external
+hints cannot be removed).
+
+A proper way to fix this issue is to bind the hints to their module scope, as
+for most of the other objects Coq uses. Hints should only be made available when
+the module they are defined in is imported, not just required. It is very
+difficult to change the historical behavior, as it would break a lot of scripts.
+We propose a smooth transitional path by providing the :opt:`Loose Hint Behavior`
+option which accepts three flags allowing for a fine-grained handling of
+non-imported hints.
+
+.. opt:: Loose Hint Behavior {| "Lax" | "Warn" | "Strict" }
+ :name: Loose Hint Behavior
+
+ This option accepts three values, which control the behavior of hints w.r.t.
+ :cmd:`Import`:
+
+ - "Lax": this is the default, and corresponds to the historical behavior,
+ that is, hints defined outside of a section have a global scope.
+
+ - "Warn": outputs a warning when a non-imported hint is used. Note that this
+ is an over-approximation, because a hint may be triggered by a run that
+ will eventually fail and backtrack, resulting in the hint not being
+ actually useful for the proof.
+
+ - "Strict": changes the behavior of an unloaded hint to a immediate fail
+ tactic, allowing to emulate an import-scoped hint mechanism.
+
+.. _tactics-implicit-automation:
+
+Setting implicit automation tactics
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. cmd:: Proof with @tactic
+
+ This command may be used to start a proof. It defines a default tactic
+ to be used each time a tactic command ``tactic``:sub:`1` is ended by ``...``.
+ In this case the tactic command typed by the user is equivalent to
+ ``tactic``:sub:`1` ``;tactic``.
+
+ .. seealso:: :cmd:`Proof` in :ref:`proof-editing-mode`.
+
+
+ .. cmdv:: Proof with @tactic using {+ @ident}
+
+ Combines in a single line ``Proof with`` and ``Proof using``, see :ref:`proof-editing-mode`
+
+ .. cmdv:: Proof using {+ @ident} with @tactic
+
+ Combines in a single line ``Proof with`` and ``Proof using``, see :ref:`proof-editing-mode`
diff --git a/doc/sphinx/proofs/automatic-tactics/index.rst b/doc/sphinx/proofs/automatic-tactics/index.rst
index a219770c69..c3712b109d 100644
--- a/doc/sphinx/proofs/automatic-tactics/index.rst
+++ b/doc/sphinx/proofs/automatic-tactics/index.rst
@@ -1,20 +1,22 @@
.. _automatic-tactics:
=====================================================
-Built-in decision procedures and programmable tactics
+Automatic solvers and programmable tactics
=====================================================
Some tactics are largely automated and are able to solve complex
-goals. This chapter presents both some decision procedures that can
-be used to solve some specific categories of goals, and some
-programmable tactics, that the user can instrument to handle some
+goals. This chapter presents both built-in solvers that can
+be used on specific categories of goals and
+programmable tactics that the user can instrument to handle
complex goals in new domains.
.. toctree::
:maxdepth: 1
+ logic
../../addendum/omega
../../addendum/micromega
../../addendum/ring
../../addendum/nsatz
+ auto
../../addendum/generalized-rewriting
diff --git a/doc/sphinx/proofs/automatic-tactics/logic.rst b/doc/sphinx/proofs/automatic-tactics/logic.rst
new file mode 100644
index 0000000000..5aaded2726
--- /dev/null
+++ b/doc/sphinx/proofs/automatic-tactics/logic.rst
@@ -0,0 +1,228 @@
+.. _decisionprocedures:
+
+==============================
+Solvers for logic and equality
+==============================
+
+.. tacn:: tauto
+
+ This tactic implements a decision procedure for intuitionistic propositional
+ calculus based on the contraction-free sequent calculi LJT* of Roy Dyckhoff
+ :cite:`Dyc92`. Note that :tacn:`tauto` succeeds on any instance of an
+ intuitionistic tautological proposition. :tacn:`tauto` unfolds negations and
+ logical equivalence but does not unfold any other definition.
+
+ .. example::
+
+ The following goal can be proved by :tacn:`tauto` whereas :tacn:`auto` would
+ fail:
+
+ .. coqtop:: reset all
+
+ Goal forall (x:nat) (P:nat -> Prop), x = 0 \/ P x -> x <> 0 -> P x.
+ intros.
+ tauto.
+
+ Moreover, if it has nothing else to do, :tacn:`tauto` performs introductions.
+ Therefore, the use of :tacn:`intros` in the previous proof is unnecessary.
+ :tacn:`tauto` can for instance for:
+
+ .. example::
+
+ .. coqtop:: reset all
+
+ Goal forall (A:Prop) (P:nat -> Prop), A \/ (forall x:nat, ~ A -> P x) -> forall x:nat, ~ A -> P x.
+ tauto.
+
+ .. note::
+ In contrast, :tacn:`tauto` cannot solve the following goal
+ :g:`Goal forall (A:Prop) (P:nat -> Prop), A \/ (forall x:nat, ~ A -> P x) ->`
+ :g:`forall x:nat, ~ ~ (A \/ P x).`
+ because :g:`(forall x:nat, ~ A -> P x)` cannot be treated as atomic and
+ an instantiation of `x` is necessary.
+
+ .. tacn:: dtauto
+
+ While :tacn:`tauto` recognizes inductively defined connectives isomorphic to
+ the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``,
+ ``Empty_set``, ``unit`` and ``True``, :tacn:`dtauto` also recognizes all inductive
+ types with one constructor and no indices, i.e. record-style connectives.
+
+.. todo would be nice to explain/discuss the various types of flags
+ that define the differences between these tactics. See Tauto.v/tauto.ml.
+
+.. tacn:: intuition {? @ltac_expr }
+
+ Uses the search tree built by the decision procedure for :tacn:`tauto`
+ to generate a set of subgoals equivalent to the original one (but
+ simpler than it) and applies :n:`@ltac_expr` to them :cite:`Mun94`. If
+ :n:`@ltac_expr` is not specified, it defaults to :n:`auto with *`
+ If :n:`@ltac_expr` fails on some goals then :tacn:`intuition` fails. In fact,
+ :tacn:`tauto` is simply :g:`intuition fail`.
+
+ :tacn:`intuition` recognizes inductively defined connectives
+ isomorphic to the standard connectives ``and``, ``prod``, ``or``, ``sum``, ``False``,
+ ``Empty_set``, ``unit`` and ``True``.
+
+ .. example::
+
+ For instance, the tactic :g:`intuition auto` applied to the goal::
+
+ (forall (x:nat), P x) /\ B -> (forall (y:nat), P y) /\ P O \/ B /\ P O
+
+ internally replaces it by the equivalent one::
+
+ (forall (x:nat), P x), B |- P O
+
+ and then uses :tacn:`auto` which completes the proof.
+
+ .. tacn:: dintuition {? @ltac_expr }
+
+ In addition to the inductively defined connectives recognized by :tacn:`intuition`,
+ :tacn:`dintuition` also recognizes all inductive
+ types with one constructor and no indices, i.e. record-style connectives.
+
+ .. flag:: Intuition Negation Unfolding
+
+ Controls whether :tacn:`intuition` unfolds inner negations which do not need
+ to be unfolded. The flag is on by default.
+
+.. tacn:: rtauto
+
+ Solves propositional tautologies similarly to
+ :tacn:`tauto`, but the proof term is built using a
+ reflection scheme applied to a sequent calculus proof of the goal. The search
+ procedure is also implemented using a different technique.
+
+ Users should be aware that this difference may result in faster proof search
+ but slower proof checking, and :tacn:`rtauto` might not solve goals that
+ :tacn:`tauto` would be able to solve (e.g. goals involving universal
+ quantifiers).
+
+ Note that this tactic is only available after a ``Require Import Rtauto``.
+
+.. tacn:: firstorder {? @ltac_expr } {? using {+, @qualid } } {? with {+ @ident } }
+
+ An experimental extension of :tacn:`tauto` to
+ first-order reasoning. It is not restricted to
+ usual logical connectives but instead can reason about any first-order class
+ inductive definition.
+
+ :token:`ltac_expr`
+ Tries to solve the goal with :token:`ltac_expr` when no logical rule applies.
+ If unspecified, the tactic uses the default from the :opt:`Firstorder Solver`
+ option.
+
+ :n:`using {+, @qualid }`
+ Adds the lemmas :n:`{+, @qualid }` to the proof search environment. If :n:`@qualid`
+ refers to an inductive type, its constructors are
+ added to the proof search environment.
+
+ :n:`with {+ @ident }`
+ Adds lemmas from :tacn:`auto` hint bases :n:`{+ @ident }` to the proof search
+ environment.
+
+ .. opt:: Firstorder Solver @ltac_expr
+
+ The default tactic used by :tacn:`firstorder` when no rule applies in
+ :g:`auto with core`. It can be set locally or globally using this option.
+
+ .. cmd:: Print Firstorder Solver
+
+ Prints the default tactic used by :tacn:`firstorder` when no rule applies.
+
+ .. opt:: Firstorder Depth @natural
+
+ Controls the proof search depth bound.
+
+.. tacn:: congruence {? @natural } {? with {+ @one_term } }
+
+ :token:`natural`
+ Specifies the maximum number of hypotheses stating quantified equalities that may be added
+ to the problem in order to solve it. The default is 1000.
+
+ :n:`{? with {+ @one_term } }`
+ Adds :n:`{+ @one_term }` to the pool of terms used by :tacn:`congruence`. This helps
+ in case you have partially applied constructors in your goal.
+
+ Implements the standard
+ Nelson and Oppen congruence closure algorithm, which is a decision procedure
+ for ground equalities with uninterpreted symbols. It also includes
+ constructor theory (see :tacn:`injection` and :tacn:`discriminate`). If the goal
+ is a non-quantified equality, congruence tries to prove it with non-quantified
+ equalities in the context. Otherwise it tries to infer a discriminable equality
+ from those in the context. Alternatively, congruence tries to prove that a
+ hypothesis is equal to the goal or to the negation of another hypothesis.
+
+ :tacn:`congruence` is also able to take advantage of hypotheses stating
+ quantified equalities, but you have to provide a bound for the number of extra
+ equalities generated that way. Please note that one of the sides of the
+ equality must contain all the quantified variables in order for congruence to
+ match against it.
+
+ Increasing the maximum number of hypotheses may solve
+ problems that would have failed with a smaller value. It will make failures slower but it
+ won't make successes found with the smaller value any slower.
+ You may want to use :tacn:`assert` to add some lemmas as
+ hypotheses so that :tacn:`congruence` can use them.
+
+ .. example::
+
+ .. coqtop:: reset all
+
+ Theorem T (A:Type) (f:A -> A) (g: A -> A -> A) a b: a=(f a) -> (g b (f a))=(f (f a)) -> (g a b)=(f (g b a)) -> (g a b)=a.
+ intros.
+ congruence.
+ Qed.
+
+ Theorem inj (A:Type) (f:A -> A * A) (a c d: A) : f = pair a -> Some (f c) = Some (f d) -> c=d.
+ intros.
+ congruence.
+ Qed.
+
+ .. exn:: I don’t know how to handle dependent equality.
+
+ The decision procedure managed to find a proof of the goal or of a
+ discriminable equality but this proof could not be built in Coq because of
+ dependently-typed functions.
+
+ .. exn:: Goal is solvable by congruence but some arguments are missing. Try congruence with {+ @term}, replacing metavariables by arbitrary terms.
+
+ The decision procedure could solve the goal with the provision that additional
+ arguments are supplied for some partially applied constructors. Any term of an
+ appropriate type will allow the tactic to successfully solve the goal. Those
+ additional arguments can be given to congruence by filling in the holes in the
+ terms given in the error message, using the `with` clause.
+
+ .. flag:: Congruence Verbose
+
+ Makes :tacn:`congruence` print debug information.
+
+.. tacn:: btauto
+
+ The tactic :tacn:`btauto` implements a reflexive solver for boolean
+ tautologies. It solves goals of the form :g:`t = u` where `t` and `u` are
+ constructed over the following grammar:
+
+ .. prodn::
+ btauto_term ::= @ident
+ | true
+ | false
+ | orb @btauto_term @btauto_term
+ | andb @btauto_term @btauto_term
+ | xorb @btauto_term @btauto_term
+ | negb @btauto_term
+ | if @btauto_term then @btauto_term else @btauto_term
+
+ Whenever the formula supplied is not a tautology, it also provides a
+ counter-example.
+
+ Internally, it uses a system very similar to the one of the ring
+ tactic.
+
+ Note that this tactic is only available after a ``Require Import Btauto``.
+
+ .. exn:: Cannot recognize a boolean equality.
+
+ The goal is not of the form :g:`t = u`. Especially note that :tacn:`btauto`
+ doesn't introduce variables into the context on its own.
diff --git a/doc/sphinx/proofs/creating-tactics/index.rst b/doc/sphinx/proofs/creating-tactics/index.rst
index f1d4fa789d..1af1b0b726 100644
--- a/doc/sphinx/proofs/creating-tactics/index.rst
+++ b/doc/sphinx/proofs/creating-tactics/index.rst
@@ -18,13 +18,13 @@ new tactics:
- `Mtac2 <https://github.com/Mtac2/Mtac2>`_ is an external plugin
which provides another typed tactic language. While Ltac2 belongs
- to the ML language family, Mtac2 reuses the language of |Coq| itself
- as the language to build |Coq| tactics.
+ to the ML language family, Mtac2 reuses the language of Coq itself
+ as the language to build Coq tactics.
- The most traditional way of building new complex tactics is to write
- a |Coq| plugin in |OCaml|. Beware that this also requires much more
- effort and commitment. A tutorial for writing |Coq| plugins is
- available in the |Coq| repository in `doc/plugin_tutorial
+ a Coq plugin in OCaml. Beware that this also requires much more
+ effort and commitment. A tutorial for writing Coq plugins is
+ available in the Coq repository in `doc/plugin_tutorial
<https://github.com/coq/coq/tree/master/doc/plugin_tutorial>`_.
.. toctree::
diff --git a/doc/sphinx/proofs/writing-proofs/index.rst b/doc/sphinx/proofs/writing-proofs/index.rst
index 3f5526dba8..7724d7433c 100644
--- a/doc/sphinx/proofs/writing-proofs/index.rst
+++ b/doc/sphinx/proofs/writing-proofs/index.rst
@@ -1,10 +1,10 @@
.. _writing-proofs:
-==============
-Writing proofs
-==============
+===================
+Basic proof writing
+===================
-|Coq| is an interactive theorem prover, or proof assistant, which means
+Coq is an interactive theorem prover, or proof assistant, which means
that proofs can be constructed interactively through a dialog between
the user and the assistant. The building blocks for this dialog are
tactics which the user will use to represent steps in the proof of a
@@ -27,8 +27,9 @@ flavors of tactics, including the SSReflect proof language.
.. toctree::
:maxdepth: 1
- ../../proof-engine/proof-handling
+ proof-mode
../../proof-engine/tactics
+ rewriting
../../proof-engine/ssreflect-proof-language
../../proof-engine/detailed-tactic-examples
../../user-extensions/proof-schemes
diff --git a/doc/sphinx/proofs/writing-proofs/proof-mode.rst b/doc/sphinx/proofs/writing-proofs/proof-mode.rst
new file mode 100644
index 0000000000..fd8a0329d6
--- /dev/null
+++ b/doc/sphinx/proofs/writing-proofs/proof-mode.rst
@@ -0,0 +1,1037 @@
+.. _proofhandling:
+
+-------------------
+ Proof handling
+-------------------
+
+In Coq’s proof editing mode all top-level commands documented in
+Chapter :ref:`vernacularcommands` remain available and the user has access to specialized
+commands dealing with proof development pragmas documented in this
+section. They can also use some other specialized commands called
+*tactics*. They are the very tools allowing the user to deal with
+logical reasoning. They are documented in Chapter :ref:`tactics`.
+
+Coq user interfaces usually have a way of marking whether the user has
+switched to proof editing mode. For instance, in coqtop the prompt ``Coq <``   is changed into
+:n:`@ident <`   where :token:`ident` is the declared name of the theorem currently edited.
+
+At each stage of a proof development, one has a list of goals to
+prove. Initially, the list consists only in the theorem itself. After
+having applied some tactics, the list of goals contains the subgoals
+generated by the tactics.
+
+To each subgoal is associated a number of hypotheses called the *local context*
+of the goal. Initially, the local context contains the local variables and
+hypotheses of the current section (see Section :ref:`gallina-assumptions`) and
+the local variables and hypotheses of the theorem statement. It is enriched by
+the use of certain tactics (see e.g. :tacn:`intro`).
+
+When a proof is completed, the message ``Proof completed`` is displayed.
+One can then register this proof as a defined constant in the
+environment. Because there exists a correspondence between proofs and
+terms of λ-calculus, known as the *Curry-Howard isomorphism*
+:cite:`How80,Bar81,Gir89,H89`, Coq stores proofs as terms of |Cic|. Those
+terms are called *proof terms*.
+
+
+.. exn:: No focused proof.
+
+ Coq raises this error message when one attempts to use a proof editing command
+ out of the proof editing mode.
+
+.. _proof-editing-mode:
+
+Entering and leaving proof editing mode
+---------------------------------------
+
+The proof editing mode is entered by asserting a statement, which typically is
+the assertion of a theorem using an assertion command like :cmd:`Theorem`. The
+list of assertion commands is given in :ref:`Assertions`. The command
+:cmd:`Goal` can also be used.
+
+.. cmd:: Goal @type
+
+ This is intended for quick assertion of statements, without knowing in
+ advance which name to give to the assertion, typically for quick
+ testing of the provability of a statement. If the proof of the
+ statement is eventually completed and validated, the statement is then
+ bound to the name ``Unnamed_thm`` (or a variant of this name not already
+ used for another statement).
+
+.. cmd:: Qed
+
+ This command is available in interactive editing proof mode when the
+ proof is completed. Then :cmd:`Qed` extracts a proof term from the proof
+ script, switches back to Coq top-level and attaches the extracted
+ proof term to the declared name of the original goal. The name is
+ added to the environment as an opaque constant.
+
+ .. exn:: Attempt to save an incomplete proof.
+ :undocumented:
+
+ .. note::
+
+ Sometimes an error occurs when building the proof term, because
+ tactics do not enforce completely the term construction
+ constraints.
+
+ The user should also be aware of the fact that since the
+ proof term is completely rechecked at this point, one may have to wait
+ a while when the proof is large. In some exceptional cases one may
+ even incur a memory overflow.
+
+.. cmd:: Save @ident
+ :name: Save
+
+ Saves a completed proof with the name :token:`ident`, which
+ overrides any name provided by the :cmd:`Theorem` command or
+ its variants.
+
+.. cmd:: Defined {? @ident }
+
+ Similar to :cmd:`Qed` and :cmd:`Save`, except the proof is made *transparent*, which means
+ that its content can be explicitly used for type checking and that it can be
+ unfolded in conversion tactics (see :ref:`performingcomputations`,
+ :cmd:`Opaque`, :cmd:`Transparent`). If :token:`ident` is specified,
+ the proof is defined with the given name, which overrides any name
+ provided by the :cmd:`Theorem` command or its variants.
+
+.. cmd:: Admitted
+
+ This command is available in interactive editing mode to give up
+ the current proof and declare the initial goal as an axiom.
+
+.. cmd:: Abort {? {| All | @ident } }
+
+ Cancels the current proof development, switching back to
+ the previous proof development, or to the Coq toplevel if no other
+ proof was being edited.
+
+ :n:`@ident`
+ Aborts editing the proof named :n:`@ident` for use when you have
+ nested proofs. See also :flag:`Nested Proofs Allowed`.
+
+ :n:`All`
+ Aborts all current proofs.
+
+ .. exn:: No focused proof (No proof-editing in progress).
+ :undocumented:
+
+.. cmd:: Proof @term
+ :name: Proof `term`
+
+ This command applies in proof editing mode. It is equivalent to
+ :n:`exact @term. Qed.`
+ That is, you have to give the full proof in one gulp, as a
+ proof term (see Section :ref:`applyingtheorems`).
+
+ .. warning::
+
+ Use of this command is discouraged. In particular, it
+ doesn't work in Proof General because it must
+ immediately follow the command that opened proof mode, but
+ Proof General inserts :cmd:`Unset` :flag:`Silent` before it (see
+ `Proof General issue #498
+ <https://github.com/ProofGeneral/PG/issues/498>`_).
+
+.. cmd:: Proof
+
+ Is a no-op which is useful to delimit the sequence of tactic commands
+ which start a proof, after a :cmd:`Theorem` command. It is a good practice to
+ use :cmd:`Proof` as an opening parenthesis, closed in the script with a
+ closing :cmd:`Qed`.
+
+ .. seealso:: :cmd:`Proof with`
+
+.. cmd:: Proof using @section_var_expr {? with @ltac_expr }
+
+ .. insertprodn section_var_expr starred_ident_ref
+
+ .. prodn::
+ section_var_expr ::= {* @starred_ident_ref }
+ | {? - } @section_var_expr50
+ section_var_expr50 ::= @section_var_expr0 - @section_var_expr0
+ | @section_var_expr0 + @section_var_expr0
+ | @section_var_expr0
+ section_var_expr0 ::= @starred_ident_ref
+ | ( @section_var_expr ) {? * }
+ starred_ident_ref ::= @ident {? * }
+ | Type {? * }
+ | All
+
+ Opens proof editing mode, declaring the set of
+ section variables (see :ref:`gallina-assumptions`) used by the proof.
+ At :cmd:`Qed` time, the
+ system verifies that the set of section variables used in
+ the proof is a subset of the declared one.
+
+ The set of declared variables is closed under type dependency. For
+ example, if ``T`` is a variable and ``a`` is a variable of type
+ ``T``, then the commands ``Proof using a`` and ``Proof using T a``
+ are equivalent.
+
+ The set of declared variables always includes the variables used by
+ the statement. In other words ``Proof using e`` is equivalent to
+ ``Proof using Type + e`` for any declaration expression ``e``.
+
+ :n:`- @section_var_expr50`
+ Use all section variables except those specified by :n:`@section_var_expr50`
+
+ :n:`@section_var_expr0 + @section_var_expr0`
+ Use section variables from the union of both collections.
+ See :ref:`nameaset` to see how to form a named collection.
+
+ :n:`@section_var_expr0 - @section_var_expr0`
+ Use section variables which are in the first collection but not in the
+ second one.
+
+ :n:`{? * }`
+ Use the transitive closure of the specified collection.
+
+ :n:`Type`
+ Use only section variables occurring in the statement. Specifying :n:`*`
+ uses the forward transitive closure of all the section variables occurring
+ in the statement. For example, if the variable ``H`` has type ``p < 5`` then
+ ``H`` is in ``p*`` since ``p`` occurs in the type of ``H``.
+
+ :n:`All`
+ Use all section variables.
+
+ .. seealso:: :ref:`tactics-implicit-automation`
+
+.. attr:: using
+
+ This attribute can be applied to the :cmd:`Definition`, :cmd:`Example`,
+ :cmd:`Fixpoint` and :cmd:`CoFixpoint` commands as well as to :cmd:`Lemma` and
+ its variants. It takes
+ a :n:`@section_var_expr`, in quotes, as its value. This is equivalent to
+ specifying the same :n:`@section_var_expr` in
+ :cmd:`Proof using`.
+
+ .. example::
+
+ .. coqtop:: all
+
+ Section Test.
+ Variable n : nat.
+ Hypothesis Hn : n <> 0.
+
+ #[using="Hn"]
+ Lemma example : 0 < n.
+
+ .. coqtop:: in
+
+ Abort.
+ End Test.
+
+
+Proof using options
+```````````````````
+
+The following options modify the behavior of ``Proof using``.
+
+
+.. opt:: Default Proof Using "@section_var_expr"
+ :name: Default Proof Using
+
+ Use :n:`@section_var_expr` as the default ``Proof using`` value. E.g. ``Set Default
+ Proof Using "a b"`` will complete all ``Proof`` commands not followed by a
+ ``using`` part with ``using a b``.
+
+
+.. flag:: Suggest Proof Using
+
+ When :cmd:`Qed` is performed, suggest a ``using`` annotation if the user did not
+ provide one.
+
+.. _`nameaset`:
+
+Name a set of section hypotheses for ``Proof using``
+````````````````````````````````````````````````````
+
+.. cmd:: Collection @ident := @section_var_expr
+
+ This can be used to name a set of section
+ hypotheses, with the purpose of making ``Proof using`` annotations more
+ compact.
+
+ .. example::
+
+ Define the collection named ``Some`` containing ``x``, ``y`` and ``z``::
+
+ Collection Some := x y z.
+
+ Define the collection named ``Fewer`` containing only ``x`` and ``y``::
+
+ Collection Fewer := Some - z
+
+ Define the collection named ``Many`` containing the set union or set
+ difference of ``Fewer`` and ``Some``::
+
+ Collection Many := Fewer + Some
+ Collection Many := Fewer - Some
+
+ Define the collection named ``Many`` containing the set difference of
+ ``Fewer`` and the unnamed collection ``x y``::
+
+ Collection Many := Fewer - (x y)
+
+
+
+.. cmd:: Existential @natural {? : @type } := @term
+
+ This command instantiates an existential variable. :token:`natural` is an index in
+ the list of uninstantiated existential variables displayed by :cmd:`Show Existentials`.
+
+ This command is intended to be used to instantiate existential
+ variables when the proof is completed but some uninstantiated
+ existential variables remain. To instantiate existential variables
+ during proof edition, you should use the tactic :tacn:`instantiate`.
+
+.. cmd:: Grab Existential Variables
+
+ This command can be run when a proof has no more goal to be solved but
+ has remaining uninstantiated existential variables. It takes every
+ uninstantiated existential variable and turns it into a goal.
+
+Proof modes
+```````````
+
+When entering proof mode through commands such as :cmd:`Goal` and :cmd:`Proof`,
+Coq picks by default the |Ltac| mode. Nonetheless, there exist other proof modes
+shipped in the standard Coq installation, and furthermore some plugins define
+their own proof modes. The default proof mode used when opening a proof can
+be changed using the following option.
+
+.. opt:: Default Proof Mode @string
+
+ Select the proof mode to use when starting a proof. Depending on the proof
+ mode, various syntactic constructs are allowed when writing an interactive
+ proof. All proof modes support vernacular commands; the proof mode determines
+ which tactic language and set of tactic definitions are available. The
+ possible option values are:
+
+ `"Classic"`
+ Activates the |Ltac| language and the tactics with the syntax documented
+ in this manual.
+ Some tactics are not available until the associated plugin is loaded,
+ such as `SSR` or `micromega`.
+ This proof mode is set when the :term:`prelude` is loaded.
+
+ `"Noedit"`
+ No tactic
+ language is activated at all. This is the default when the :term:`prelude`
+ is not loaded, e.g. through the `-noinit` option for `coqc`.
+
+ `"Ltac2"`
+ Activates the Ltac2 language and the Ltac2-specific variants of the documented
+ tactics.
+ This value is only available after :cmd:`Requiring <Require>` Ltac2.
+ :cmd:`Importing <Import>` Ltac2 sets this mode.
+
+ Some external plugins also define their own proof mode, which can be
+ activated with this command.
+
+Navigation in the proof tree
+--------------------------------
+
+.. cmd:: Undo {? {? To } @natural }
+
+ Cancels the effect of the last :token:`natural` commands or tactics.
+ The :n:`To @natural` form goes back to the specified state number.
+ If :token:`natural` is not specified, the command goes back one command or tactic.
+
+.. cmd:: Restart
+
+ Restores the proof editing process to the original goal.
+
+ .. exn:: No focused proof to restart.
+ :undocumented:
+
+.. cmd:: Focus {? @natural }
+
+ Focuses the attention on the first subgoal to prove or, if :token:`natural` is
+ specified, the :token:`natural`\-th. The
+ printing of the other subgoals is suspended until the focused subgoal
+ is solved or unfocused.
+
+ .. deprecated:: 8.8
+
+ Prefer the use of bullets or focusing brackets with a goal selector (see below).
+
+.. cmd:: Unfocus
+
+ This command restores to focus the goal that were suspended by the
+ last :cmd:`Focus` command.
+
+ .. deprecated:: 8.8
+
+.. cmd:: Unfocused
+
+ Succeeds if the proof is fully unfocused, fails if there are some
+ goals out of focus.
+
+.. _curly-braces:
+
+.. index:: {
+ }
+
+.. todo: :name: "{"; "}" doesn't work, nor does :name: left curly bracket; right curly bracket,
+ hence the verbose names
+
+.. tacn:: {? {| @natural | [ @ident ] } : } %{
+ %}
+
+ .. todo
+ See https://github.com/coq/coq/issues/12004 and
+ https://github.com/coq/coq/issues/12825.
+
+ ``{`` (without a terminating period) focuses on the first
+ goal. The subproof can only be
+ unfocused when it has been fully solved (*i.e.*, when there is no
+ focused goal left). Unfocusing is then handled by ``}`` (again, without a
+ terminating period). See also an example in the next section.
+
+ Note that when a focused goal is proved a message is displayed
+ together with a suggestion about the right bullet or ``}`` to unfocus it
+ or focus the next one.
+
+ :n:`@natural:`
+ Focuses on the :token:`natural`\-th subgoal to prove.
+
+ :n:`[ @ident ]: %{`
+ Focuses on the named goal :token:`ident`.
+
+ .. note::
+
+ Goals are just existential variables and existential variables do not
+ get a name by default. You can give a name to a goal by using :n:`refine ?[@ident]`.
+ You may also wrap this in an Ltac-definition like:
+
+ .. coqtop:: in
+
+ Ltac name_goal name := refine ?[name].
+
+ .. seealso:: :ref:`existential-variables`
+
+ .. example::
+
+ This first example uses the Ltac definition above, and the named goals
+ only serve for documentation.
+
+ .. coqtop:: all
+
+ Goal forall n, n + 0 = n.
+ Proof.
+ induction n; [ name_goal base | name_goal step ].
+ [base]: {
+
+ .. coqtop:: all
+
+ reflexivity.
+
+ .. coqtop:: in
+
+ }
+
+ .. coqtop:: all
+
+ [step]: {
+
+ .. coqtop:: all
+
+ simpl.
+ f_equal.
+ assumption.
+ }
+ Qed.
+
+ This can also be a way of focusing on a shelved goal, for instance:
+
+ .. coqtop:: all
+
+ Goal exists n : nat, n = n.
+ eexists ?[x].
+ reflexivity.
+ [x]: exact 0.
+ Qed.
+
+ .. exn:: This proof is focused, but cannot be unfocused this way.
+
+ You are trying to use ``}`` but the current subproof has not been fully solved.
+
+ .. exn:: No such goal (@natural).
+ :undocumented:
+
+ .. exn:: No such goal (@ident).
+ :undocumented:
+
+ .. exn:: Brackets do not support multi-goal selectors.
+
+ Brackets are used to focus on a single goal given either by its position
+ or by its name if it has one.
+
+ .. seealso:: The error messages for bullets below.
+
+.. _bullets:
+
+Bullets
+```````
+
+Alternatively, proofs can be structured with bullets instead of ``{`` and ``}``. The
+use of a bullet ``b`` for the first time focuses on the first goal ``g``, the
+same bullet cannot be used again until the proof of ``g`` is completed,
+then it is mandatory to focus the next goal with ``b``. The consequence is
+that ``g`` and all goals present when ``g`` was focused are focused with the
+same bullet ``b``. See the example below.
+
+Different bullets can be used to nest levels. The scope of bullet does
+not go beyond enclosing ``{`` and ``}``, so bullets can be reused as further
+nesting levels provided they are delimited by these. Bullets are made of
+repeated ``-``, ``+`` or ``*`` symbols:
+
+.. prodn:: bullet ::= {| {+ - } | {+ + } | {+ * } }
+
+Note again that when a focused goal is proved a message is displayed
+together with a suggestion about the right bullet or ``}`` to unfocus it
+or focus the next one.
+
+.. note::
+
+ In Proof General (``Emacs`` interface to Coq), you must use
+ bullets with the priority ordering shown above to have a correct
+ indentation. For example ``-`` must be the outer bullet and ``**`` the inner
+ one in the example below.
+
+The following example script illustrates all these features:
+
+.. example::
+
+ .. coqtop:: all
+
+ Goal (((True /\ True) /\ True) /\ True) /\ True.
+ Proof.
+ split.
+ - split.
+ + split.
+ ** { split.
+ - trivial.
+ - trivial.
+ }
+ ** trivial.
+ + trivial.
+ - assert True.
+ { trivial. }
+ assumption.
+ Qed.
+
+.. exn:: Wrong bullet @bullet__1: Current bullet @bullet__2 is not finished.
+
+ Before using bullet :n:`@bullet__1` again, you should first finish proving
+ the current focused goal.
+ Note that :n:`@bullet__1` and :n:`@bullet__2` may be the same.
+
+.. exn:: Wrong bullet @bullet__1: Bullet @bullet__2 is mandatory here.
+
+ You must put :n:`@bullet__2` to focus on the next goal. No other bullet is
+ allowed here.
+
+.. exn:: No such goal. Focus next goal with bullet @bullet.
+
+ You tried to apply a tactic but no goals were under focus.
+ Using :n:`@bullet` is mandatory here.
+
+.. FIXME: the :noindex: below works around a Sphinx issue.
+ (https://github.com/sphinx-doc/sphinx/issues/4979)
+ It should be removed once that issue is fixed.
+
+.. exn:: No such goal. Try unfocusing with %}.
+ :noindex:
+
+ You just finished a goal focused by ``{``, you must unfocus it with ``}``.
+
+Mandatory Bullets
+~~~~~~~~~~~~~~~~~
+
+Using :opt:`Default Goal Selector` with the ``!`` selector forces
+tactic scripts to keep focus to exactly one goal (e.g. using bullets)
+or use explicit goal selectors.
+
+Set Bullet Behavior
+~~~~~~~~~~~~~~~~~~~
+
+.. opt:: Bullet Behavior {| "None" | "Strict Subproofs" }
+ :name: Bullet Behavior
+
+ This option controls the bullet behavior and can take two possible values:
+
+ - "None": this makes bullets inactive.
+ - "Strict Subproofs": this makes bullets active (this is the default behavior).
+
+Modifying the order of goals
+````````````````````````````
+
+.. tacn:: cycle @integer
+ :name: cycle
+
+ Reorders the selected goals so that the first :n:`@integer` goals appear after the
+ other selected goals.
+ If :n:`@integer` is negative, it puts the last :n:`@integer` goals at the
+ beginning of the list.
+ The tactic is only useful with a goal selector, most commonly `all:`.
+ Note that other selectors reorder goals; `1,3: cycle 1` is not equivalent
+ to `all: cycle 1`. See :tacn:`… : … (goal selector)`.
+
+.. example::
+
+ .. coqtop:: none reset
+
+ Parameter P : nat -> Prop.
+
+ .. coqtop:: all abort
+
+ Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5.
+ repeat split.
+ all: cycle 2.
+ all: cycle -3.
+
+.. tacn:: swap @integer @integer
+ :name: swap
+
+ Exchanges the position of the specified goals.
+ Negative values for :n:`@integer` indicate counting goals
+ backward from the end of the list of selected goals. Goals are indexed from 1.
+ The tactic is only useful with a goal selector, most commonly `all:`.
+ Note that other selectors reorder goals; `1,3: swap 1 3` is not equivalent
+ to `all: swap 1 3`. See :tacn:`… : … (goal selector)`.
+
+.. example::
+
+ .. coqtop:: all abort
+
+ Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5.
+ repeat split.
+ all: swap 1 3.
+ all: swap 1 -1.
+
+.. tacn:: revgoals
+ :name: revgoals
+
+ Reverses the order of the selected goals. The tactic is only useful with a goal
+ selector, most commonly `all :`. Note that other selectors reorder goals;
+ `1,3: revgoals` is not equivalent to `all: revgoals`. See :tacn:`… : … (goal selector)`.
+
+ .. example::
+
+ .. coqtop:: all abort
+
+ Goal P 1 /\ P 2 /\ P 3 /\ P 4 /\ P 5.
+ repeat split.
+ all: revgoals.
+
+Postponing the proof of some goals
+``````````````````````````````````
+
+.. tacn:: shelve
+ :name: shelve
+
+ This tactic moves all goals under focus to a shelf. While on the
+ shelf, goals will not be focused on. They can be solved by
+ unification, or they can be called back into focus with the command
+ :cmd:`Unshelve`.
+
+ .. tacv:: shelve_unifiable
+ :name: shelve_unifiable
+
+ Shelves only the goals under focus that are mentioned in other goals.
+ Goals that appear in the type of other goals can be solved by unification.
+
+ .. example::
+
+ .. coqtop:: all abort
+
+ Goal exists n, n=0.
+ refine (ex_intro _ _ _).
+ all: shelve_unifiable.
+ reflexivity.
+
+.. cmd:: Unshelve
+
+ This command moves all the goals on the shelf (see :tacn:`shelve`)
+ from the shelf into focus, by appending them to the end of the current
+ list of focused goals.
+
+.. tacn:: unshelve @tactic
+ :name: unshelve
+
+ Performs :n:`@tactic`, then unshelves existential variables added to the
+ shelf by the execution of :n:`@tactic`, prepending them to the current goal.
+
+.. tacn:: give_up
+ :name: give_up
+
+ This tactic removes the focused goals from the proof. They are not
+ solved, and cannot be solved later in the proof. As the goals are not
+ solved, the proof cannot be closed.
+
+ The ``give_up`` tactic can be used while editing a proof, to choose to
+ write the proof script in a non-sequential order.
+
+.. _requestinginformation:
+
+Requesting information
+----------------------
+
+
+.. cmd:: Show {? {| @ident | @natural } }
+
+ Displays the current goals.
+
+ :n:`@natural`
+ Display only the :token:`natural`\-th subgoal.
+
+ :n:`@ident`
+ Displays the named goal :token:`ident`. This is useful in
+ particular to display a shelved goal but only works if the
+ corresponding existential variable has been named by the user
+ (see :ref:`existential-variables`) as in the following example.
+
+ .. example::
+
+ .. coqtop:: all abort
+
+ Goal exists n, n = 0.
+ eexists ?[n].
+ Show n.
+
+ .. exn:: No focused proof.
+ :undocumented:
+
+ .. exn:: No such goal.
+ :undocumented:
+
+.. cmd:: Show Proof {? Diffs {? removed } }
+
+ Displays the proof term generated by the tactics
+ that have been applied so far. If the proof is incomplete, the term
+ will contain holes, which correspond to subterms which are still to be
+ constructed. Each hole is an existential variable, which appears as a
+ question mark followed by an identifier.
+
+ Specifying “Diffs” highlights the difference between the
+ current and previous proof step. By default, the command shows the
+ output once with additions highlighted. Including “removed” shows
+ the output twice: once showing removals and once showing additions.
+ It does not examine the :opt:`Diffs` option. See :ref:`showing_proof_diffs`.
+
+.. cmd:: Show Conjectures
+
+ Prints the names of all the
+ theorems that are currently being proved. As it is possible to start
+ proving a previous lemma during the proof of a theorem, there may
+ be multiple names.
+
+.. cmd:: Show Intro
+
+ If the current goal begins by at least one product,
+ prints the name of the first product as it would be
+ generated by an anonymous :tacn:`intro`. The aim of this command is to ease
+ the writing of more robust scripts. For example, with an appropriate
+ Proof General macro, it is possible to transform any anonymous :tacn:`intro`
+ into a qualified one such as ``intro y13``. In the case of a non-product
+ goal, it prints nothing.
+
+.. cmd:: Show Intros
+
+ Similar to the previous command.
+ Simulates the naming process of :tacn:`intros`.
+
+.. cmd:: Show Existentials
+
+ Displays all open goals / existential variables in the current proof
+ along with the type and the context of each variable.
+
+.. cmd:: Show Match @qualid
+
+ Displays a template of the Gallina :token:`match<term_match>`
+ construct with a branch for each constructor of the type
+ :token:`qualid`. This is used internally by
+ `company-coq <https://github.com/cpitclaudel/company-coq>`_.
+
+ .. example::
+
+ .. coqtop:: all
+
+ Show Match nat.
+
+ .. exn:: Unknown inductive type.
+ :undocumented:
+
+.. cmd:: Show Universes
+
+ Displays the set of all universe constraints and
+ its normalized form at the current stage of the proof, useful for
+ debugging universe inconsistencies.
+
+.. cmd:: Show Goal @natural at @natural
+
+ Available in coqtop. Displays a goal at a
+ proof state using the goal ID number and the proof state ID number.
+ It is primarily for use by tools such as Prooftree that need to fetch
+ goal history in this way. Prooftree is a tool for visualizing a proof
+ as a tree that runs in Proof General.
+
+.. cmd:: Guarded
+
+ Some tactics (e.g. :tacn:`refine`) allow to build proofs using
+ fixpoint or co-fixpoint constructions. Due to the incremental nature
+ of interactive proof construction, the check of the termination (or
+ guardedness) of the recursive calls in the fixpoint or cofixpoint
+ constructions is postponed to the time of the completion of the proof.
+
+ The command :cmd:`Guarded` allows checking if the guard condition for
+ fixpoint and cofixpoint is violated at some time of the construction
+ of the proof without having to wait the completion of the proof.
+
+.. _showing_diffs:
+
+Showing differences between proof steps
+---------------------------------------
+
+Coq can automatically highlight the differences between successive proof steps
+and between values in some error messages. Coq can also highlight differences
+in the proof term.
+For example, the following screenshots of CoqIDE and coqtop show the application
+of the same :tacn:`intros` tactic. The tactic creates two new hypotheses, highlighted in green.
+The conclusion is entirely in pale green because although it’s changed, no tokens were added
+to it. The second screenshot uses the "removed" option, so it shows the conclusion a
+second time with the old text, with deletions marked in red. Also, since the hypotheses are
+new, no line of old text is shown for them.
+
+.. comment screenshot produced with:
+ Inductive ev : nat -> Prop :=
+ | ev_0 : ev 0
+ | ev_SS : forall n : nat, ev n -> ev (S (S n)).
+
+ Fixpoint double (n:nat) :=
+ match n with
+ | O => O
+ | S n' => S (S (double n'))
+ end.
+
+ Goal forall n, ev n -> exists k, n = double k.
+ intros n E.
+
+..
+
+ .. image:: ../../_static/diffs-coqide-on.png
+ :alt: CoqIDE with Set Diffs on
+
+..
+
+ .. image:: ../../_static/diffs-coqide-removed.png
+ :alt: CoqIDE with Set Diffs removed
+
+..
+
+ .. image:: ../../_static/diffs-coqtop-on3.png
+ :alt: coqtop with Set Diffs on
+
+This image shows an error message with diff highlighting in CoqIDE:
+
+..
+
+ .. image:: ../../_static/diffs-error-message.png
+ :alt: CoqIDE error message with diffs
+
+How to enable diffs
+```````````````````
+
+.. opt:: Diffs {| "on" | "off" | "removed" }
+ :name: Diffs
+
+ The “on” setting highlights added tokens in green, while the “removed” setting
+ additionally reprints items with removed tokens in red. Unchanged tokens in
+ modified items are shown with pale green or red. Diffs in error messages
+ use red and green for the compared values; they appear regardless of the setting.
+ (Colors are user-configurable.)
+
+For coqtop, showing diffs can be enabled when starting coqtop with the
+``-diffs on|off|removed`` command-line option or by setting the :opt:`Diffs` option
+within Coq. You will need to provide the ``-color on|auto`` command-line option when
+you start coqtop in either case.
+
+Colors for coqtop can be configured by setting the ``COQ_COLORS`` environment
+variable. See section :ref:`customization-by-environment-variables`. Diffs
+use the tags ``diff.added``, ``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg``.
+
+In CoqIDE, diffs should be enabled from the ``View`` menu. Don’t use the ``Set Diffs``
+command in CoqIDE. You can change the background colors shown for diffs from the
+``Edit | Preferences | Tags`` panel by changing the settings for the ``diff.added``,
+``diff.added.bg``, ``diff.removed`` and ``diff.removed.bg`` tags. This panel also
+lets you control other attributes of the highlights, such as the foreground
+color, bold, italic, underline and strikeout.
+
+Proof General can also display Coq-generated proof diffs automatically.
+Please see the PG documentation section
+"`Showing Proof Diffs" <https://proofgeneral.github.io/doc/master/userman/Coq-Proof-General#Showing-Proof-Diffs>`_)
+for details.
+
+How diffs are calculated
+````````````````````````
+
+Diffs are calculated as follows:
+
+1. Select the old proof state to compare to, which is the proof state before
+ the last tactic that changed the proof. Changes that only affect the view
+ of the proof, such as ``all: swap 1 2``, are ignored.
+
+2. For each goal in the new proof state, determine what old goal to compare
+ it to—the one it is derived from or is the same as. Match the hypotheses by
+ name (order is ignored), handling compacted items specially.
+
+3. For each hypothesis and conclusion (the “items”) in each goal, pass
+ them as strings to the lexer to break them into tokens. Then apply the
+ Myers diff algorithm :cite:`Myers` on the tokens and add appropriate highlighting.
+
+Notes:
+
+* Aside from the highlights, output for the "on" option should be identical
+ to the undiffed output.
+* Goals completed in the last proof step will not be shown even with the
+ "removed" setting.
+
+.. comment The following screenshots show diffs working with multiple goals and with compacted
+ hypotheses. In the first one, notice that the goal ``P 1`` is not highlighted at
+ all after the split because it has not changed.
+
+ .. todo: Use this script and remove the screenshots when COQ_COLORS
+ works for coqtop in sphinx
+ .. coqtop:: none
+
+ Set Diffs "on".
+ Parameter P : nat -> Prop.
+ Goal P 1 /\ P 2 /\ P 3.
+
+ .. coqtop:: out
+
+ split.
+
+ .. coqtop:: all abort
+
+ 2: split.
+
+ ..
+
+ .. coqtop:: none
+
+ Set Diffs "on".
+ Goal forall n m : nat, n + m = m + n.
+ Set Diffs "on".
+
+ .. coqtop:: out
+
+ intros n.
+
+ .. coqtop:: all abort
+
+ intros m.
+
+This screen shot shows the result of applying a :tacn:`split` tactic that replaces one goal
+with 2 goals. Notice that the goal ``P 1`` is not highlighted at all after
+the split because it has not changed.
+
+..
+
+ .. image:: ../../_static/diffs-coqide-multigoal.png
+ :alt: coqide with Set Diffs on with multiple goals
+
+Diffs may appear like this after applying a :tacn:`intro` tactic that results
+in a compacted hypotheses:
+
+..
+
+ .. image:: ../../_static/diffs-coqide-compacted.png
+ :alt: coqide with Set Diffs on with compacted hypotheses
+
+.. _showing_proof_diffs:
+
+"Show Proof" differences
+````````````````````````
+
+To show differences in the proof term:
+
+- In coqtop and Proof General, use the :cmd:`Show Proof` `Diffs` command.
+
+- In CoqIDE, position the cursor on or just after a tactic to compare the proof term
+ after the tactic with the proof term before the tactic, then select
+ `View / Show Proof` from the menu or enter the associated key binding.
+ Differences will be shown applying the current `Show Diffs` setting
+ from the `View` menu. If the current setting is `Don't show diffs`, diffs
+ will not be shown.
+
+ Output with the "added and removed" option looks like this:
+
+ ..
+
+ .. image:: ../../_static/diffs-show-proof.png
+ :alt: coqide with Set Diffs on with compacted hypotheses
+
+Controlling the effect of proof editing commands
+------------------------------------------------
+
+
+.. opt:: Hyps Limit @natural
+ :name: Hyps Limit
+
+ This option controls the maximum number of hypotheses displayed in goals
+ after the application of a tactic. All the hypotheses remain usable
+ in the proof development.
+ When unset, it goes back to the default mode which is to print all
+ available hypotheses.
+
+
+.. flag:: Nested Proofs Allowed
+
+ When turned on (it is off by default), this flag enables support for nested
+ proofs: a new assertion command can be inserted before the current proof is
+ finished, in which case Coq will temporarily switch to the proof of this
+ *nested lemma*. When the proof of the nested lemma is finished (with :cmd:`Qed`
+ or :cmd:`Defined`), its statement will be made available (as if it had been
+ proved before starting the previous proof) and Coq will switch back to the
+ proof of the previous assertion.
+
+.. flag:: Printing Goal Names
+
+ When turned on, the name of the goal is printed in interactive
+ proof mode, which can be useful in cases of cross references
+ between goals.
+
+Controlling memory usage
+------------------------
+
+.. cmd:: Print Debug GC
+
+ Prints heap usage statistics, which are values from the `stat` type of the `Gc` module
+ described
+ `here <https://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#TYPEstat>`_
+ in the OCaml documentation.
+ The `live_words`, `heap_words` and `top_heap_words` values give the basic information.
+ Words are 8 bytes or 4 bytes, respectively, for 64- and 32-bit executables.
+
+When experiencing high memory usage the following commands can be used
+to force Coq to optimize some of its internal data structures.
+
+.. cmd:: Optimize Proof
+
+ Shrink the data structure used to represent the current proof.
+
+
+.. cmd:: Optimize Heap
+
+ Perform a heap compaction. This is generally an expensive operation.
+ See: `OCaml Gc.compact <http://caml.inria.fr/pub/docs/manual-ocaml/libref/Gc.html#VALcompact>`_
+ There is also an analogous tactic :tacn:`optimize_heap`.
+
+Memory usage parameters can be set through the :ref:`OCAMLRUNPARAM <OCAMLRUNPARAM>`
+environment variable.
diff --git a/doc/sphinx/proofs/writing-proofs/rewriting.rst b/doc/sphinx/proofs/writing-proofs/rewriting.rst
new file mode 100644
index 0000000000..f3f69a2fdc
--- /dev/null
+++ b/doc/sphinx/proofs/writing-proofs/rewriting.rst
@@ -0,0 +1,857 @@
+=================================
+Term rewriting and simplification
+=================================
+
+.. _rewritingexpressions:
+
+Rewriting expressions
+---------------------
+
+These tactics use the equality :g:`eq:forall A:Type, A->A->Prop` defined in
+file ``Logic.v`` (see :ref:`coq-library-logic`). The notation for :g:`eq T t u` is
+simply :g:`t=u` dropping the implicit type of :g:`t` and :g:`u`.
+
+.. tacn:: rewrite @term
+ :name: rewrite
+
+ This tactic applies to any goal. The type of :token:`term` must have the form
+
+ ``forall (x``:sub:`1` ``:A``:sub:`1` ``) ... (x``:sub:`n` ``:A``:sub:`n` ``), eq term``:sub:`1` ``term``:sub:`2` ``.``
+
+ where :g:`eq` is the Leibniz equality or a registered setoid equality.
+
+ Then :n:`rewrite @term` finds the first subterm matching `term`\ :sub:`1` in the goal,
+ resulting in instances `term`:sub:`1`' and `term`:sub:`2`' and then
+ replaces every occurrence of `term`:subscript:`1`' by `term`:subscript:`2`'.
+ Hence, some of the variables :g:`x`\ :sub:`i` are solved by unification,
+ and some of the types :g:`A`\ :sub:`1`:g:`, ..., A`\ :sub:`n` become new
+ subgoals.
+
+ .. exn:: The @term provided does not end with an equation.
+ :undocumented:
+
+ .. exn:: Tactic generated a subgoal identical to the original goal. This happens if @term does not occur in the goal.
+ :undocumented:
+
+ .. tacv:: rewrite -> @term
+
+ Is equivalent to :n:`rewrite @term`
+
+ .. tacv:: rewrite <- @term
+
+ Uses the equality :n:`@term`:sub:`1` :n:`= @term` :sub:`2` from right to left
+
+ .. tacv:: rewrite @term in @goal_occurrences
+
+ Analogous to :n:`rewrite @term` but rewriting is done following
+ the clause :token:`goal_occurrences`. For instance:
+
+ + :n:`rewrite H in H'` will rewrite `H` in the hypothesis
+ ``H'`` instead of the current goal.
+ + :n:`rewrite H in H' at 1, H'' at - 2 |- *` means
+ :n:`rewrite H; rewrite H in H' at 1; rewrite H in H'' at - 2.`
+ In particular a failure will happen if any of these three simpler tactics
+ fails.
+ + :n:`rewrite H in * |-` will do :n:`rewrite H in H'` for all hypotheses
+ :g:`H'` different from :g:`H`.
+ A success will happen as soon as at least one of these simpler tactics succeeds.
+ + :n:`rewrite H in *` is a combination of :n:`rewrite H` and :n:`rewrite H in * |-`
+ that succeeds if at least one of these two tactics succeeds.
+
+ Orientation :g:`->` or :g:`<-` can be inserted before the :token:`term` to rewrite.
+
+ .. tacv:: rewrite @term at @occurrences
+
+ Rewrite only the given :token:`occurrences` of :token:`term`. Occurrences are
+ specified from left to right as for pattern (:tacn:`pattern`). The rewrite is
+ always performed using setoid rewriting, even for Leibniz’s equality, so one
+ has to ``Import Setoid`` to use this variant.
+
+ .. tacv:: rewrite @term by @tactic
+
+ Use tactic to completely solve the side-conditions arising from the
+ :tacn:`rewrite`.
+
+ .. tacv:: rewrite {+, @orientation @term} {? in @ident }
+
+ Is equivalent to the `n` successive tactics :n:`{+; rewrite @term}`, each one
+ working on the first subgoal generated by the previous one. An :production:`orientation`
+ ``->`` or ``<-`` can be inserted before each :token:`term` to rewrite. One
+ unique clause can be added at the end after the keyword in; it will then
+ affect all rewrite operations.
+
+ In all forms of rewrite described above, a :token:`term` to rewrite can be
+ immediately prefixed by one of the following modifiers:
+
+ + `?` : the tactic :n:`rewrite ?@term` performs the rewrite of :token:`term` as many
+ times as possible (perhaps zero time). This form never fails.
+ + :n:`@natural?` : works similarly, except that it will do at most :token:`natural` rewrites.
+ + `!` : works as `?`, except that at least one rewrite should succeed, otherwise
+ the tactic fails.
+ + :n:`@natural!` (or simply :n:`@natural`) : precisely :token:`natural` rewrites of :token:`term` will be done,
+ leading to failure if these :token:`natural` rewrites are not possible.
+
+ .. tacv:: erewrite @term
+ :name: erewrite
+
+ This tactic works as :n:`rewrite @term` but turning
+ unresolved bindings into existential variables, if any, instead of
+ failing. It has the same variants as :tacn:`rewrite` has.
+
+ .. flag:: Keyed Unification
+
+ Makes higher-order unification used by :tacn:`rewrite` rely on a set of keys to drive
+ unification. The subterms, considered as rewriting candidates, must start with
+ the same key as the left- or right-hand side of the lemma given to rewrite, and the arguments
+ are then unified up to full reduction.
+
+.. tacn:: replace @term with @term’
+ :name: replace
+
+ This tactic applies to any goal. It replaces all free occurrences of :n:`@term`
+ in the current goal with :n:`@term’` and generates an equality :n:`@term = @term’`
+ as a subgoal. This equality is automatically solved if it occurs among
+ the assumptions, or if its symmetric form occurs. It is equivalent to
+ :n:`cut @term = @term’; [intro H`:sub:`n` :n:`; rewrite <- H`:sub:`n` :n:`; clear H`:sub:`n`:n:`|| assumption || symmetry; try assumption]`.
+
+ .. exn:: Terms do not have convertible types.
+ :undocumented:
+
+ .. tacv:: replace @term with @term’ by @tactic
+
+ This acts as :n:`replace @term with @term’` but applies :token:`tactic` to solve the generated
+ subgoal :n:`@term = @term’`.
+
+ .. tacv:: replace @term
+
+ Replaces :n:`@term` with :n:`@term’` using the first assumption whose type has
+ the form :n:`@term = @term’` or :n:`@term’ = @term`.
+
+ .. tacv:: replace -> @term
+
+ Replaces :n:`@term` with :n:`@term’` using the first assumption whose type has
+ the form :n:`@term = @term’`
+
+ .. tacv:: replace <- @term
+
+ Replaces :n:`@term` with :n:`@term’` using the first assumption whose type has
+ the form :n:`@term’ = @term`
+
+ .. tacv:: replace @term {? with @term} in @goal_occurrences {? by @tactic}
+ replace -> @term in @goal_occurrences
+ replace <- @term in @goal_occurrences
+
+ Acts as before but the replacements take place in the specified clauses
+ (:token:`goal_occurrences`) (see :ref:`performingcomputations`) and not
+ only in the conclusion of the goal. The clause argument must not contain
+ any ``type of`` nor ``value of``.
+
+.. tacn:: subst @ident
+ :name: subst
+
+ This tactic applies to a goal that has :n:`@ident` in its context and (at
+ least) one hypothesis, say :g:`H`, of type :n:`@ident = t` or :n:`t = @ident`
+ with :n:`@ident` not occurring in :g:`t`. Then it replaces :n:`@ident` by
+ :g:`t` everywhere in the goal (in the hypotheses and in the conclusion) and
+ clears :n:`@ident` and :g:`H` from the context.
+
+ If :n:`@ident` is a local definition of the form :n:`@ident := t`, it is also
+ unfolded and cleared.
+
+ If :n:`@ident` is a section variable it is expected to have no
+ indirect occurrences in the goal, i.e. that no global declarations
+ implicitly depending on the section variable must be present in the
+ goal.
+
+ .. note::
+ + When several hypotheses have the form :n:`@ident = t` or :n:`t = @ident`, the
+ first one is used.
+
+ + If :g:`H` is itself dependent in the goal, it is replaced by the proof of
+ reflexivity of equality.
+
+ .. tacv:: subst {+ @ident}
+
+ This is equivalent to :n:`subst @ident`:sub:`1`:n:`; ...; subst @ident`:sub:`n`.
+
+ .. tacv:: subst
+
+ This applies :tacn:`subst` repeatedly from top to bottom to all hypotheses of the
+ context for which an equality of the form :n:`@ident = t` or :n:`t = @ident`
+ or :n:`@ident := t` exists, with :n:`@ident` not occurring in
+ ``t`` and :n:`@ident` not a section variable with indirect
+ dependencies in the goal.
+
+ .. flag:: Regular Subst Tactic
+
+ This flag controls the behavior of :tacn:`subst`. When it is
+ activated (it is by default), :tacn:`subst` also deals with the following corner cases:
+
+ + A context with ordered hypotheses :n:`@ident`:sub:`1` :n:`= @ident`:sub:`2`
+ and :n:`@ident`:sub:`1` :n:`= t`, or :n:`t′ = @ident`:sub:`1`` with `t′` not
+ a variable, and no other hypotheses of the form :n:`@ident`:sub:`2` :n:`= u`
+ or :n:`u = @ident`:sub:`2`; without the flag, a second call to
+ subst would be necessary to replace :n:`@ident`:sub:`2` by `t` or
+ `t′` respectively.
+ + The presence of a recursive equation which without the flag would
+ be a cause of failure of :tacn:`subst`.
+ + A context with cyclic dependencies as with hypotheses :n:`@ident`:sub:`1` :n:`= f @ident`:sub:`2`
+ and :n:`@ident`:sub:`2` :n:`= g @ident`:sub:`1` which without the
+ flag would be a cause of failure of :tacn:`subst`.
+
+ Additionally, it prevents a local definition such as :n:`@ident := t` to be
+ unfolded which otherwise it would exceptionally unfold in configurations
+ containing hypotheses of the form :n:`@ident = u`, or :n:`u′ = @ident`
+ with `u′` not a variable. Finally, it preserves the initial order of
+ hypotheses, which without the flag it may break.
+ default.
+
+ .. exn:: Cannot find any non-recursive equality over :n:`@ident`.
+ :undocumented:
+
+ .. exn:: Section variable :n:`@ident` occurs implicitly in global declaration :n:`@qualid` present in hypothesis :n:`@ident`.
+ Section variable :n:`@ident` occurs implicitly in global declaration :n:`@qualid` present in the conclusion.
+
+ Raised when the variable is a section variable with indirect
+ dependencies in the goal.
+
+
+.. tacn:: stepl @term
+ :name: stepl
+
+ This tactic is for chaining rewriting steps. It assumes a goal of the
+ form :n:`R @term @term` where ``R`` is a binary relation and relies on a
+ database of lemmas of the form :g:`forall x y z, R x y -> eq x z -> R z y`
+ where `eq` is typically a setoid equality. The application of :n:`stepl @term`
+ then replaces the goal by :n:`R @term @term` and adds a new goal stating
+ :n:`eq @term @term`.
+
+ .. cmd:: Declare Left Step @term
+
+ Adds :n:`@term` to the database used by :tacn:`stepl`.
+
+ This tactic is especially useful for parametric setoids which are not accepted
+ as regular setoids for :tacn:`rewrite` and :tacn:`setoid_replace` (see
+ :ref:`Generalizedrewriting`).
+
+ .. tacv:: stepl @term by @tactic
+
+ This applies :n:`stepl @term` then applies :token:`tactic` to the second goal.
+
+ .. tacv:: stepr @term by @tactic
+ :name: stepr
+
+ This behaves as :tacn:`stepl` but on the right-hand-side of the binary
+ relation. Lemmas are expected to be of the form
+ :g:`forall x y z, R x y -> eq y z -> R x z`.
+
+ .. cmd:: Declare Right Step @term
+
+ Adds :n:`@term` to the database used by :tacn:`stepr`.
+
+
+.. tacn:: change @term
+ :name: change
+
+ This tactic applies to any goal. It implements the rule ``Conv`` given in
+ :ref:`subtyping-rules`. :g:`change U` replaces the current goal `T`
+ with `U` providing that `U` is well-formed and that `T` and `U` are
+ convertible.
+
+ .. exn:: Not convertible.
+ :undocumented:
+
+ .. tacv:: change @term with @term’
+
+ This replaces the occurrences of :n:`@term` by :n:`@term’` in the current goal.
+ The term :n:`@term` and :n:`@term’` must be convertible.
+
+ .. tacv:: change @term at {+ @natural} with @term’
+
+ This replaces the occurrences numbered :n:`{+ @natural}` of :n:`@term` by :n:`@term’`
+ in the current goal. The terms :n:`@term` and :n:`@term’` must be convertible.
+
+ .. exn:: Too few occurrences.
+ :undocumented:
+
+ .. tacv:: change @term {? {? at {+ @natural}} with @term} in @ident
+
+ This applies the :tacn:`change` tactic not to the goal but to the hypothesis :n:`@ident`.
+
+ .. tacv:: now_show @term
+
+ This is a synonym of :n:`change @term`. It can be used to
+ make some proof steps explicit when refactoring a proof script
+ to make it readable.
+
+ .. seealso:: :ref:`Performing computations <performingcomputations>`
+
+.. _performingcomputations:
+
+Performing computations
+---------------------------
+
+.. insertprodn red_expr pattern_occ
+
+.. prodn::
+ red_expr ::= red
+ | hnf
+ | simpl {? @delta_flag } {? @ref_or_pattern_occ }
+ | cbv {? @strategy_flag }
+ | cbn {? @strategy_flag }
+ | lazy {? @strategy_flag }
+ | compute {? @delta_flag }
+ | vm_compute {? @ref_or_pattern_occ }
+ | native_compute {? @ref_or_pattern_occ }
+ | unfold {+, @unfold_occ }
+ | fold {+ @one_term }
+ | pattern {+, @pattern_occ }
+ | @ident
+ delta_flag ::= {? - } [ {+ @reference } ]
+ strategy_flag ::= {+ @red_flag }
+ | @delta_flag
+ red_flag ::= beta
+ | iota
+ | match
+ | fix
+ | cofix
+ | zeta
+ | delta {? @delta_flag }
+ ref_or_pattern_occ ::= @reference {? at @occs_nums }
+ | @one_term {? at @occs_nums }
+ occs_nums ::= {+ {| @natural | @ident } }
+ | - {| @natural | @ident } {* @int_or_var }
+ int_or_var ::= @integer
+ | @ident
+ unfold_occ ::= @reference {? at @occs_nums }
+ pattern_occ ::= @one_term {? at @occs_nums }
+
+This set of tactics implements different specialized usages of the
+tactic :tacn:`change`.
+
+All conversion tactics (including :tacn:`change`) can be parameterized by the
+parts of the goal where the conversion can occur. This is done using
+*goal clauses* which consists in a list of hypotheses and, optionally,
+of a reference to the conclusion of the goal. For defined hypothesis
+it is possible to specify if the conversion should occur on the type
+part, the body part or both (default).
+
+Goal clauses are written after a conversion tactic (tactics :tacn:`set`,
+:tacn:`rewrite`, :tacn:`replace` and :tacn:`autorewrite` also use goal
+clauses) and are introduced by the keyword `in`. If no goal clause is
+provided, the default is to perform the conversion only in the
+conclusion.
+
+The syntax and description of the various goal clauses is the
+following:
+
++ :n:`in {+ @ident} |-` only in hypotheses :n:`{+ @ident}`
++ :n:`in {+ @ident} |- *` in hypotheses :n:`{+ @ident}` and in the
+ conclusion
++ :n:`in * |-` in every hypothesis
++ :n:`in *` (equivalent to in :n:`* |- *`) everywhere
++ :n:`in (type of @ident) (value of @ident) ... |-` in type part of
+ :n:`@ident`, in the value part of :n:`@ident`, etc.
+
+For backward compatibility, the notation :n:`in {+ @ident}` performs
+the conversion in hypotheses :n:`{+ @ident}`.
+
+.. tacn:: cbv {? @strategy_flag }
+ lazy {? @strategy_flag }
+ :name: cbv; lazy
+
+ These parameterized reduction tactics apply to any goal and perform
+ the normalization of the goal according to the specified flags. In
+ correspondence with the kinds of reduction considered in Coq namely
+ :math:`\beta` (reduction of functional application), :math:`\delta`
+ (unfolding of transparent constants, see :ref:`vernac-controlling-the-reduction-strategies`),
+ :math:`\iota` (reduction of
+ pattern matching over a constructed term, and unfolding of :g:`fix` and
+ :g:`cofix` expressions) and :math:`\zeta` (contraction of local definitions), the
+ flags are either ``beta``, ``delta``, ``match``, ``fix``, ``cofix``,
+ ``iota`` or ``zeta``. The ``iota`` flag is a shorthand for ``match``, ``fix``
+ and ``cofix``. The ``delta`` flag itself can be refined into
+ :n:`delta [ {+ @qualid} ]` or :n:`delta - [ {+ @qualid} ]`, restricting in the first
+ case the constants to unfold to the constants listed, and restricting in the
+ second case the constant to unfold to all but the ones explicitly mentioned.
+ Notice that the ``delta`` flag does not apply to variables bound by a let-in
+ construction inside the :n:`@term` itself (use here the ``zeta`` flag). In
+ any cases, opaque constants are not unfolded (see :ref:`vernac-controlling-the-reduction-strategies`).
+
+ Normalization according to the flags is done by first evaluating the
+ head of the expression into a *weak-head* normal form, i.e. until the
+ evaluation is blocked by a variable (or an opaque constant, or an
+ axiom), as e.g. in :g:`x u1 ... un` , or :g:`match x with ... end`, or
+ :g:`(fix f x {struct x} := ...) x`, or is a constructed form (a
+ :math:`\lambda`-expression, a constructor, a cofixpoint, an inductive type, a
+ product type, a sort), or is a redex that the flags prevent to reduce. Once a
+ weak-head normal form is obtained, subterms are recursively reduced using the
+ same strategy.
+
+ Reduction to weak-head normal form can be done using two strategies:
+ *lazy* (``lazy`` tactic), or *call-by-value* (``cbv`` tactic). The lazy
+ strategy is a call-by-need strategy, with sharing of reductions: the
+ arguments of a function call are weakly evaluated only when necessary,
+ and if an argument is used several times then it is weakly computed
+ only once. This reduction is efficient for reducing expressions with
+ dead code. For instance, the proofs of a proposition :g:`exists x. P(x)`
+ reduce to a pair of a witness :g:`t`, and a proof that :g:`t` satisfies the
+ predicate :g:`P`. Most of the time, :g:`t` may be computed without computing
+ the proof of :g:`P(t)`, thanks to the lazy strategy.
+
+ The call-by-value strategy is the one used in ML languages: the
+ arguments of a function call are systematically weakly evaluated
+ first. Despite the lazy strategy always performs fewer reductions than
+ the call-by-value strategy, the latter is generally more efficient for
+ evaluating purely computational expressions (i.e. with little dead code).
+
+.. tacv:: compute
+ cbv
+ :name: compute; _
+
+ These are synonyms for ``cbv beta delta iota zeta``.
+
+.. tacv:: lazy
+
+ This is a synonym for ``lazy beta delta iota zeta``.
+
+.. tacv:: compute [ {+ @qualid} ]
+ cbv [ {+ @qualid} ]
+
+ These are synonyms of :n:`cbv beta delta {+ @qualid} iota zeta`.
+
+.. tacv:: compute - [ {+ @qualid} ]
+ cbv - [ {+ @qualid} ]
+
+ These are synonyms of :n:`cbv beta delta -{+ @qualid} iota zeta`.
+
+.. tacv:: lazy [ {+ @qualid} ]
+ lazy - [ {+ @qualid} ]
+
+ These are respectively synonyms of :n:`lazy beta delta {+ @qualid} iota zeta`
+ and :n:`lazy beta delta -{+ @qualid} iota zeta`.
+
+.. tacv:: vm_compute
+ :name: vm_compute
+
+ This tactic evaluates the goal using the optimized call-by-value evaluation
+ bytecode-based virtual machine described in :cite:`CompiledStrongReduction`.
+ This algorithm is dramatically more efficient than the algorithm used for the
+ :tacn:`cbv` tactic, but it cannot be fine-tuned. It is especially interesting for
+ full evaluation of algebraic objects. This includes the case of
+ reflection-based tactics.
+
+.. tacv:: native_compute
+ :name: native_compute
+
+ This tactic evaluates the goal by compilation to OCaml as described
+ in :cite:`FullReduction`. If Coq is running in native code, it can be
+ typically two to five times faster than :tacn:`vm_compute`. Note however that the
+ compilation cost is higher, so it is worth using only for intensive
+ computations.
+
+ .. flag:: NativeCompute Timing
+
+ This flag causes all calls to the native compiler to print
+ timing information for the conversion to native code,
+ compilation, execution, and reification phases of native
+ compilation. Timing is printed in units of seconds of
+ wall-clock time.
+
+ .. flag:: NativeCompute Profiling
+
+ On Linux, if you have the ``perf`` profiler installed, this flag makes
+ it possible to profile :tacn:`native_compute` evaluations.
+
+ .. opt:: NativeCompute Profile Filename @string
+ :name: NativeCompute Profile Filename
+
+ This option specifies the profile output; the default is
+ ``native_compute_profile.data``. The actual filename used
+ will contain extra characters to avoid overwriting an existing file; that
+ filename is reported to the user.
+ That means you can individually profile multiple uses of
+ :tacn:`native_compute` in a script. From the Linux command line, run ``perf report``
+ on the profile file to see the results. Consult the ``perf`` documentation
+ for more details.
+
+.. flag:: Debug Cbv
+
+ This flag makes :tacn:`cbv` (and its derivative :tacn:`compute`) print
+ information about the constants it encounters and the unfolding decisions it
+ makes.
+
+.. tacn:: red
+ :name: red
+
+ This tactic applies to a goal that has the form::
+
+ forall (x:T1) ... (xk:Tk), T
+
+ with :g:`T` :math:`\beta`:math:`\iota`:math:`\zeta`-reducing to :g:`c t`:sub:`1` :g:`... t`:sub:`n` and :g:`c` a
+ constant. If :g:`c` is transparent then it replaces :g:`c` with its
+ definition (say :g:`t`) and then reduces
+ :g:`(t t`:sub:`1` :g:`... t`:sub:`n` :g:`)` according to :math:`\beta`:math:`\iota`:math:`\zeta`-reduction rules.
+
+.. exn:: Not reducible.
+ :undocumented:
+
+.. exn:: No head constant to reduce.
+ :undocumented:
+
+.. tacn:: hnf
+ :name: hnf
+
+ This tactic applies to any goal. It replaces the current goal with its
+ head normal form according to the :math:`\beta`:math:`\delta`:math:`\iota`:math:`\zeta`-reduction rules, i.e. it
+ reduces the head of the goal until it becomes a product or an
+ irreducible term. All inner :math:`\beta`:math:`\iota`-redexes are also reduced.
+ The behavior of both :tacn:`hnf` can be tuned using the :cmd:`Arguments` command.
+
+ Example: The term :g:`fun n : nat => S n + S n` is not reduced by :n:`hnf`.
+
+.. note::
+ The :math:`\delta` rule only applies to transparent constants (see :ref:`vernac-controlling-the-reduction-strategies`
+ on transparency and opacity).
+
+.. tacn:: cbn
+ simpl
+ :name: cbn; simpl
+
+ These tactics apply to any goal. They try to reduce a term to
+ something still readable instead of fully normalizing it. They perform
+ a sort of strong normalization with two key differences:
+
+ + They unfold a constant if and only if it leads to a :math:`\iota`-reduction,
+ i.e. reducing a match or unfolding a fixpoint.
+ + While reducing a constant unfolding to (co)fixpoints, the tactics
+ use the name of the constant the (co)fixpoint comes from instead of
+ the (co)fixpoint definition in recursive calls.
+
+ The :tacn:`cbn` tactic is claimed to be a more principled, faster and more
+ predictable replacement for :tacn:`simpl`.
+
+ The :tacn:`cbn` tactic accepts the same flags as :tacn:`cbv` and
+ :tacn:`lazy`. The behavior of both :tacn:`simpl` and :tacn:`cbn`
+ can be tuned using the :cmd:`Arguments` command.
+
+ .. todo add "See <subsection about controlling the behavior of reduction strategies>"
+ to TBA section
+
+ Notice that only transparent constants whose name can be reused in the
+ recursive calls are possibly unfolded by :tacn:`simpl`. For instance a
+ constant defined by :g:`plus' := plus` is possibly unfolded and reused in
+ the recursive calls, but a constant such as :g:`succ := plus (S O)` is
+ never unfolded. This is the main difference between :tacn:`simpl` and :tacn:`cbn`.
+ The tactic :tacn:`cbn` reduces whenever it will be able to reuse it or not:
+ :g:`succ t` is reduced to :g:`S t`.
+
+.. tacv:: cbn [ {+ @qualid} ]
+ cbn - [ {+ @qualid} ]
+
+ These are respectively synonyms of :n:`cbn beta delta [ {+ @qualid} ] iota zeta`
+ and :n:`cbn beta delta - [ {+ @qualid} ] iota zeta` (see :tacn:`cbn`).
+
+.. tacv:: simpl @pattern
+
+ This applies :tacn:`simpl` only to the subterms matching
+ :n:`@pattern` in the current goal.
+
+.. tacv:: simpl @pattern at {+ @natural}
+
+ This applies :tacn:`simpl` only to the :n:`{+ @natural}` occurrences of the subterms
+ matching :n:`@pattern` in the current goal.
+
+ .. exn:: Too few occurrences.
+ :undocumented:
+
+.. tacv:: simpl @qualid
+ simpl @string
+
+ This applies :tacn:`simpl` only to the applicative subterms whose head occurrence
+ is the unfoldable constant :n:`@qualid` (the constant can be referred to by
+ its notation using :n:`@string` if such a notation exists).
+
+.. tacv:: simpl @qualid at {+ @natural}
+ simpl @string at {+ @natural}
+
+ This applies :tacn:`simpl` only to the :n:`{+ @natural}` applicative subterms whose
+ head occurrence is :n:`@qualid` (or :n:`@string`).
+
+.. flag:: Debug RAKAM
+
+ This flag makes :tacn:`cbn` print various debugging information.
+ ``RAKAM`` is the Refolding Algebraic Krivine Abstract Machine.
+
+.. tacn:: unfold @qualid
+ :name: unfold
+
+ This tactic applies to any goal. The argument qualid must denote a
+ defined transparent constant or local definition (see
+ :ref:`gallina-definitions` and
+ :ref:`vernac-controlling-the-reduction-strategies`). The tactic
+ :tacn:`unfold` applies the :math:`\delta` rule to each occurrence
+ of the constant to which :n:`@qualid` refers in the current goal
+ and then replaces it with its :math:`\beta\iota\zeta`-normal form.
+ Use the general reduction tactics if you want to avoid this final
+ reduction, for instance :n:`cbv delta [@qualid]`.
+
+ .. exn:: Cannot coerce @qualid to an evaluable reference.
+
+ This error is frequent when trying to unfold something that has
+ defined as an inductive type (or constructor) and not as a
+ definition.
+
+ .. example::
+
+ .. coqtop:: abort all fail
+
+ Goal 0 <= 1.
+ unfold le.
+
+ This error can also be raised if you are trying to unfold
+ something that has been marked as opaque.
+
+ .. example::
+
+ .. coqtop:: abort all fail
+
+ Opaque Nat.add.
+ Goal 1 + 0 = 1.
+ unfold Nat.add.
+
+ .. tacv:: unfold @qualid in @goal_occurrences
+
+ Replaces :n:`@qualid` in hypothesis (or hypotheses) designated
+ by :token:`goal_occurrences` with its definition and replaces
+ the hypothesis with its :math:`\beta`:math:`\iota` normal form.
+
+ .. tacv:: unfold {+, @qualid}
+
+ Replaces :n:`{+, @qualid}` with their definitions and replaces
+ the current goal with its :math:`\beta`:math:`\iota` normal
+ form.
+
+ .. tacv:: unfold {+, @qualid at @occurrences }
+
+ The list :token:`occurrences` specify the occurrences of
+ :n:`@qualid` to be unfolded. Occurrences are located from left
+ to right.
+
+ .. exn:: Bad occurrence number of @qualid.
+ :undocumented:
+
+ .. exn:: @qualid does not occur.
+ :undocumented:
+
+ .. tacv:: unfold @string
+
+ If :n:`@string` denotes the discriminating symbol of a notation
+ (e.g. "+") or an expression defining a notation (e.g. `"_ +
+ _"`), and this notation denotes an application whose head symbol
+ is an unfoldable constant, then the tactic unfolds it.
+
+ .. tacv:: unfold @string%@ident
+
+ This is variant of :n:`unfold @string` where :n:`@string` gets
+ its interpretation from the scope bound to the delimiting key
+ :token:`ident` instead of its default interpretation (see
+ :ref:`Localinterpretationrulesfornotations`).
+
+ .. tacv:: unfold {+, {| @qualid | @string{? %@ident } } {? at @occurrences } } {? in @goal_occurrences }
+
+ This is the most general form.
+
+.. tacn:: fold @term
+ :name: fold
+
+ This tactic applies to any goal. The term :n:`@term` is reduced using the
+ :tacn:`red` tactic. Every occurrence of the resulting :n:`@term` in the goal is
+ then replaced by :n:`@term`. This tactic is particularly useful when a fixpoint
+ definition has been wrongfully unfolded, making the goal very hard to read.
+ On the other hand, when an unfolded function applied to its argument has been
+ reduced, the :tacn:`fold` tactic won't do anything.
+
+ .. example::
+
+ .. coqtop:: all abort
+
+ Goal ~0=0.
+ unfold not.
+ Fail progress fold not.
+ pattern (0 = 0).
+ fold not.
+
+ .. tacv:: fold {+ @term}
+
+ Equivalent to :n:`fold @term ; ... ; fold @term`.
+
+.. tacn:: pattern @term
+ :name: pattern
+
+ This command applies to any goal. The argument :n:`@term` must be a free
+ subterm of the current goal. The command pattern performs :math:`\beta`-expansion
+ (the inverse of :math:`\beta`-reduction) of the current goal (say :g:`T`) by
+
+ + replacing all occurrences of :n:`@term` in :g:`T` with a fresh variable
+ + abstracting this variable
+ + applying the abstracted goal to :n:`@term`
+
+ For instance, if the current goal :g:`T` is expressible as
+ :math:`\varphi`:g:`(t)` where the notation captures all the instances of :g:`t`
+ in :math:`\varphi`:g:`(t)`, then :n:`pattern t` transforms it into
+ :g:`(fun x:A =>` :math:`\varphi`:g:`(x)) t`. This tactic can be used, for
+ instance, when the tactic ``apply`` fails on matching.
+
+.. tacv:: pattern @term at {+ @natural}
+
+ Only the occurrences :n:`{+ @natural}` of :n:`@term` are considered for
+ :math:`\beta`-expansion. Occurrences are located from left to right.
+
+.. tacv:: pattern @term at - {+ @natural}
+
+ All occurrences except the occurrences of indexes :n:`{+ @natural }`
+ of :n:`@term` are considered for :math:`\beta`-expansion. Occurrences are located from
+ left to right.
+
+.. tacv:: pattern {+, @term}
+
+ Starting from a goal :math:`\varphi`:g:`(t`:sub:`1` :g:`... t`:sub:`m`:g:`)`,
+ the tactic :n:`pattern t`:sub:`1`:n:`, ..., t`:sub:`m` generates the
+ equivalent goal
+ :g:`(fun (x`:sub:`1`:g:`:A`:sub:`1`:g:`) ... (x`:sub:`m` :g:`:A`:sub:`m` :g:`) =>`:math:`\varphi`:g:`(x`:sub:`1` :g:`... x`:sub:`m` :g:`)) t`:sub:`1` :g:`... t`:sub:`m`.
+ If :g:`t`:sub:`i` occurs in one of the generated types :g:`A`:sub:`j` these
+ occurrences will also be considered and possibly abstracted.
+
+.. tacv:: pattern {+, @term at {+ @natural}}
+
+ This behaves as above but processing only the occurrences :n:`{+ @natural}` of
+ :n:`@term` starting from :n:`@term`.
+
+.. tacv:: pattern {+, @term {? at {? -} {+, @natural}}}
+
+ This is the most general syntax that combines the different variants.
+
+.. tacn:: with_strategy @strategy_level_or_var [ {+ @reference } ] @ltac_expr3
+ :name: with_strategy
+
+ Executes :token:`ltac_expr3`, applying the alternate unfolding
+ behavior that the :cmd:`Strategy` command controls, but only for
+ :token:`ltac_expr3`. This can be useful for guarding calls to
+ reduction in tactic automation to ensure that certain constants are
+ never unfolded by tactics like :tacn:`simpl` and :tacn:`cbn` or to
+ ensure that unfolding does not fail.
+
+ .. example::
+
+ .. coqtop:: all reset abort
+
+ Opaque id.
+ Goal id 10 = 10.
+ Fail unfold id.
+ with_strategy transparent [id] unfold id.
+
+ .. warning::
+
+ Use this tactic with care, as effects do not persist past the
+ end of the proof script. Notably, this fine-tuning of the
+ conversion strategy is not in effect during :cmd:`Qed` nor
+ :cmd:`Defined`, so this tactic is most useful either in
+ combination with :tacn:`abstract`, which will check the proof
+ early while the fine-tuning is still in effect, or to guard
+ calls to conversion in tactic automation to ensure that, e.g.,
+ :tacn:`unfold` does not fail just because the user made a
+ constant :cmd:`Opaque`.
+
+ This can be illustrated with the following example involving the
+ factorial function.
+
+ .. coqtop:: in reset
+
+ Fixpoint fact (n : nat) : nat :=
+ match n with
+ | 0 => 1
+ | S n' => n * fact n'
+ end.
+
+ Suppose now that, for whatever reason, we want in general to
+ unfold the :g:`id` function very late during conversion:
+
+ .. coqtop:: in
+
+ Strategy 1000 [id].
+
+ If we try to prove :g:`id (fact n) = fact n` by
+ :tacn:`reflexivity`, it will now take time proportional to
+ :math:`n!`, because Coq will keep unfolding :g:`fact` and
+ :g:`*` and :g:`+` before it unfolds :g:`id`, resulting in a full
+ computation of :g:`fact n` (in unary, because we are using
+ :g:`nat`), which takes time :math:`n!`. We can see this cross
+ the relevant threshold at around :math:`n = 9`:
+
+ .. coqtop:: all abort
+
+ Goal True.
+ Time assert (id (fact 8) = fact 8) by reflexivity.
+ Time assert (id (fact 9) = fact 9) by reflexivity.
+
+ Note that behavior will be the same if you mark :g:`id` as
+ :g:`Opaque` because while most reduction tactics refuse to
+ unfold :g:`Opaque` constants, conversion treats :g:`Opaque` as
+ merely a hint to unfold this constant last.
+
+ We can get around this issue by using :tacn:`with_strategy`:
+
+ .. coqtop:: all
+
+ Goal True.
+ Fail Timeout 1 assert (id (fact 100) = fact 100) by reflexivity.
+ Time assert (id (fact 100) = fact 100) by with_strategy -1 [id] reflexivity.
+
+ However, when we go to close the proof, we will run into
+ trouble, because the reduction strategy changes are local to the
+ tactic passed to :tacn:`with_strategy`.
+
+ .. coqtop:: all abort fail
+
+ exact I.
+ Timeout 1 Defined.
+
+ We can fix this issue by using :tacn:`abstract`:
+
+ .. coqtop:: all
+
+ Goal True.
+ Time assert (id (fact 100) = fact 100) by with_strategy -1 [id] abstract reflexivity.
+ exact I.
+ Time Defined.
+
+ On small examples this sort of behavior doesn't matter, but
+ because Coq is a super-linear performance domain in so many
+ places, unless great care is taken, tactic automation using
+ :tacn:`with_strategy` may not be robustly performant when
+ scaling the size of the input.
+
+ .. warning::
+
+ In much the same way this tactic does not play well with
+ :cmd:`Qed` and :cmd:`Defined` without using :tacn:`abstract` as
+ an intermediary, this tactic does not play well with ``coqchk``,
+ even when used with :tacn:`abstract`, due to the inability of
+ tactics to persist information about conversion hints in the
+ proof term. See `#12200
+ <https://github.com/coq/coq/issues/12200>`_ for more details.
+
+Conversion tactics applied to hypotheses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. tacn:: @tactic in {+, @ident}
+
+ Applies :token:`tactic` (any of the conversion tactics listed in this
+ section) to the hypotheses :n:`{+ @ident}`.
+
+ If :token:`ident` is a local definition, then :token:`ident` can be replaced by
+ :n:`type of @ident` to address not the body but the type of the local
+ definition.
+
+ Example: :n:`unfold not in (type of H1) (type of H3)`.
diff --git a/doc/sphinx/refman-preamble.rst b/doc/sphinx/refman-preamble.rst
index 05e665a43b..32d3e87e68 100644
--- a/doc/sphinx/refman-preamble.rst
+++ b/doc/sphinx/refman-preamble.rst
@@ -15,15 +15,9 @@
.. |c_i| replace:: `c`\ :math:`_{i}`
.. |c_n| replace:: `c`\ :math:`_{n}`
.. |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`
.. |Latex| replace:: :smallcaps:`LaTeX`
-.. |L_tac| replace:: `L`:sub:`tac`
.. |Ltac| replace:: `L`:sub:`tac`
-.. |ML| replace:: :smallcaps:`ML`
-.. |OCaml| replace:: :smallcaps:`OCaml`
.. |p_1| replace:: `p`\ :math:`_{1}`
.. |p_i| replace:: `p`\ :math:`_{i}`
.. |p_n| replace:: `p`\ :math:`_{n}`
diff --git a/doc/sphinx/user-extensions/proof-schemes.rst b/doc/sphinx/user-extensions/proof-schemes.rst
index abecee8459..f9d4864492 100644
--- a/doc/sphinx/user-extensions/proof-schemes.rst
+++ b/doc/sphinx/user-extensions/proof-schemes.rst
@@ -129,7 +129,7 @@ Automatic declaration of schemes
.. warning::
- You have to be careful with these flags since |Coq| may now reject well-defined
+ You have to be careful with these flags since Coq may now reject well-defined
inductive types because it cannot compute a Boolean equality for them.
.. flag:: Rewriting Schemes
diff --git a/doc/sphinx/user-extensions/syntax-extensions.rst b/doc/sphinx/user-extensions/syntax-extensions.rst
index 06018304ab..f36767b207 100644
--- a/doc/sphinx/user-extensions/syntax-extensions.rst
+++ b/doc/sphinx/user-extensions/syntax-extensions.rst
@@ -3,7 +3,7 @@
Syntax extensions and notation scopes
=====================================
-In this chapter, we introduce advanced commands to modify the way |Coq|
+In this chapter, we introduce advanced commands to modify the way Coq
parses and prints objects, i.e. the translations between the concrete
and internal representations of terms and commands.
@@ -13,7 +13,7 @@ The main commands to provide custom symbolic notations for terms are
variant of :cmd:`Notation` which does not modify the parser; this provides a
form of :ref:`abbreviation <Abbreviations>`. It is
sometimes expected that the same symbolic notation has different meanings in
-different contexts; to achieve this form of overloading, |Coq| offers a notion
+different contexts; to achieve this form of overloading, Coq offers a notion
of :ref:`notation scopes <Scopes>`.
The main command to provide custom notations for tactics is :cmd:`Tactic Notation`.
@@ -71,7 +71,7 @@ least 3 characters and starting with a simple quote must be quoted
Notation "'IF' c1 'then' c2 'else' c3" := (IF_then_else c1 c2 c3).
A notation binds a syntactic expression to a term. Unless the parser
-and pretty-printer of |Coq| already know how to deal with the syntactic
+and pretty-printer of Coq already know how to deal with the syntactic
expression (such as through :cmd:`Reserved Notation` or for notations
that contain only literals), explicit precedences and
associativity rules have to be given.
@@ -88,7 +88,7 @@ Precedences and associativity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mixing different symbolic notations in the same text may cause serious
-parsing ambiguity. To deal with the ambiguity of notations, |Coq| uses
+parsing ambiguity. To deal with the ambiguity of notations, Coq uses
precedence levels ranging from 0 to 100 (plus one extra level numbered
200) and associativity rules.
@@ -99,7 +99,7 @@ Consider for example the new notation
Notation "A \/ B" := (or A B).
Clearly, an expression such as :g:`forall A:Prop, True /\ A \/ A \/ False`
-is ambiguous. To tell the |Coq| parser how to interpret the
+is ambiguous. To tell the Coq parser how to interpret the
expression, a priority between the symbols ``/\`` and ``\/`` has to be
given. Assume for instance that we want conjunction to bind more than
disjunction. This is expressed by assigning a precedence level to each
@@ -117,7 +117,7 @@ defaults to :g:`True /\ (False /\ False)` (right associativity) or to
expression is not well-formed and that parentheses are mandatory (this is a “no
associativity”) [#no_associativity]_. We do not know of a special convention for
the associativity of disjunction and conjunction, so let us apply
-right associativity (which is the choice of |Coq|).
+right associativity (which is the choice of Coq).
Precedence levels and associativity rules of notations are specified with a list of
parenthesized :n:`@syntax_modifier`\s. Here is how the previous examples refine:
@@ -187,7 +187,7 @@ left. See the next section for more about factorization.
Simple factorization rules
~~~~~~~~~~~~~~~~~~~~~~~~~~
-|Coq| extensible parsing is performed by *Camlp5* which is essentially a LL1
+Coq extensible parsing is performed by *Camlp5* which is essentially a LL1
parser: it decides which notation to parse by looking at tokens from left to right.
Hence, some care has to be taken not to hide already existing rules by new
rules. Some simple left factorization work has to be done. Here is an example.
@@ -209,16 +209,16 @@ need to force the parsing level of ``y``, as follows.
Notation "x < y" := (lt x y) (at level 70).
Notation "x < y < z" := (x < y /\ y < z) (at level 70, y at next level).
-For the sake of factorization with |Coq| predefined rules, simple rules
+For the sake of factorization with Coq predefined rules, simple rules
have to be observed for notations starting with a symbol, e.g., rules
starting with “\ ``{``\ ” or “\ ``(``\ ” should be put at level 0. The list
-of |Coq| predefined notations can be found in the chapter on :ref:`thecoqlibrary`.
+of Coq predefined notations can be found in the chapter on :ref:`thecoqlibrary`.
Displaying symbolic notations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The command :cmd:`Notation` has an effect both on the |Coq| parser and on the
-|Coq| printer. For example:
+The command :cmd:`Notation` has an effect both on the Coq parser and on the
+Coq printer. For example:
.. coqtop:: all
@@ -226,7 +226,7 @@ The command :cmd:`Notation` has an effect both on the |Coq| parser and on the
However, printing, especially pretty-printing, also requires some
care. We may want specific indentations, line breaks, alignment if on
-several lines, etc. For pretty-printing, |Coq| relies on |OCaml|
+several lines, etc. For pretty-printing, Coq relies on OCaml
formatting library, which provides indentation and automatic line
breaks depending on page width by means of *formatting boxes*.
@@ -349,12 +349,12 @@ Reserving notations
.. cmd:: Reserved Notation @string {? ( {+, @syntax_modifier } ) }
- A given notation may be used in different contexts. |Coq| expects all
+ A given notation may be used in different contexts. Coq expects all
uses of the notation to be defined at the same precedence and with the
same associativity. To avoid giving the precedence and associativity
every time, this command declares a parsing rule (:token:`string`) in advance
without giving its interpretation. Here is an example from the initial
- state of |Coq|.
+ state of Coq.
.. coqtop:: in
@@ -454,7 +454,7 @@ Displaying information about notations
definition where the nonterminal was referenced. This command shows the original grammar,
so it won't exactly match the documentation.
- The |Coq| parser is based on Camlp5. The documentation for
+ The Coq parser is based on Camlp5. The documentation for
`Extensible grammars <http://camlp5.github.io/doc/htmlc/grammars.html>`_ is the
most relevant but it assumes considerable knowledge. Here are the essentials:
@@ -521,7 +521,7 @@ Displaying information about notations
The file
`doc/tools/docgram/fullGrammar <http://github.com/coq/coq/blob/master/doc/tools/docgram/fullGrammar>`_
in the source tree extracts the full grammar for
- |Coq| (not including notations and tactic notations defined in `*.v` files nor some optionally-loaded plugins)
+ Coq (not including notations and tactic notations defined in `*.v` files nor some optionally-loaded plugins)
in a single file with minor changes to handle nonterminals using multiple levels (described in
`doc/tools/docgram/README.md <http://github.com/coq/coq/blob/master/doc/tools/docgram/README.md>`_).
This is complete and much easier to read than the grammar source files.
@@ -762,7 +762,7 @@ recursive patterns. The basic example is:
Notation "[ x ; .. ; y ]" := (cons x .. (cons y nil) ..).
On the right-hand side, an extra construction of the form ``.. t ..`` can
-be used. Notice that ``..`` is part of the |Coq| syntax and it must not be
+be used. Notice that ``..`` is part of the Coq syntax and it must not be
confused with the three-dots notation “``…``” used in this manual to denote
a sequence of arbitrary size.
@@ -942,7 +942,7 @@ Custom entries
Custom entries have levels, like the main grammar of terms and grammar
of patterns have. The lower level is 0 and this is the level used by
default to put rules delimited with tokens on both ends. The level is
-left to be inferred by |Coq| when using :n:`in custom @ident`. The
+left to be inferred by Coq when using :n:`in custom @ident`. The
level is otherwise given explicitly by using the syntax
:n:`in custom @ident at level @natural`, where :n:`@natural` refers to the level.
@@ -996,7 +996,7 @@ associated to the custom entry ``expr``. The level can be omitted, as in
Notation "[ e ]" := e (e custom expr).
-in which case |Coq| infer it. If the sub-expression is at a border of
+in which case Coq infer it. If the sub-expression is at a border of
the notation (as e.g. ``x`` and ``y`` in ``x + y``), the level is
determined by the associativity. If the sub-expression is not at the
border of the notation (as e.g. ``e`` in ``"[ e ]``), the level is
@@ -1097,7 +1097,7 @@ Here are the syntax elements used by the various notation commands.
time. Type checking is done only at the time of use of the notation.
.. note:: Some examples of Notation may be found in the files composing
- the initial state of |Coq| (see directory :file:`$COQLIB/theories/Init`).
+ the initial state of Coq (see directory :file:`$COQLIB/theories/Init`).
.. note:: The notation ``"{ x }"`` has a special status in the main grammars of
terms and patterns so that
@@ -1122,7 +1122,7 @@ Here are the syntax elements used by the various notation commands.
.. warn:: Use of @string Notation is deprecated as it is inconsistent with pattern syntax.
This warning is disabled by default to avoid spurious diagnostics
- due to legacy notation in the |Coq| standard library.
+ due to legacy notation in the Coq standard library.
It can be turned on with the ``-w disj-pattern-notation`` flag.
.. _Scopes:
@@ -1156,7 +1156,7 @@ Most commands use :token:`scope_name`; :token:`scope_key`\s are used within :tok
.. cmd:: Declare Scope @scope_name
Declares a new notation scope. Note that the initial
- state of |Coq| declares the following notation scopes:
+ state of Coq declares the following notation scopes:
``core_scope``, ``type_scope``, ``function_scope``, ``nat_scope``,
``bool_scope``, ``list_scope``, ``int_scope``, ``uint_scope``.
@@ -1167,7 +1167,7 @@ Global interpretation rules for notations
At any time, the interpretation of a notation for a term is done within
a *stack* of notation scopes and lonely notations. If a
-notation is defined in multiple scopes, |Coq| uses the interpretation from
+notation is defined in multiple scopes, Coq uses the interpretation from
the most recently opened notation scope or declared lonely notation.
Note that "stack" is a misleading name. Each scope or lonely notation can only appear in
@@ -1308,10 +1308,10 @@ recognized to be a ``Funclass`` instance, i.e., of type :g:`forall x:A, B` or
.. _notation-scopes:
-Notation scopes used in the standard library of |Coq|
+Notation scopes used in the standard library of Coq
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We give an overview of the scopes used in the standard library of |Coq|.
+We give an overview of the scopes used in the standard library of Coq.
For a complete list of notations in each scope, use the commands :cmd:`Print
Scopes` or :cmd:`Print Scope`.
@@ -1377,7 +1377,7 @@ Scopes` or :cmd:`Print Scope`.
``string_scope``
This scope includes notation for strings as elements of the type string.
- Special characters and escaping follow |Coq| conventions on strings (see
+ Special characters and escaping follow Coq conventions on strings (see
:ref:`lexical-conventions`). Especially, there is no convention to visualize non
printable characters of a string. The file :file:`String.v` shows an example
that contains quotes, a newline and a beep (i.e. the ASCII character
@@ -1386,7 +1386,7 @@ Scopes` or :cmd:`Print Scope`.
``char_scope``
This scope includes interpretation for all strings of the form ``"c"``
where :g:`c` is an ASCII character, or of the form ``"nnn"`` where nnn is
- a three-digits number (possibly with leading 0's), or of the form
+ a three-digit number (possibly with leading 0s), or of the form
``""""``. Their respective denotations are the ASCII code of :g:`c`, the
decimal ASCII code ``nnn``, or the ascii code of the character ``"`` (i.e.
the ASCII code 34), all of them being represented in the type :g:`ascii`.
@@ -1478,7 +1478,7 @@ Abbreviations
An abbreviation expects no precedence nor associativity, since it
is parsed as an usual application. Abbreviations are used as
- much as possible by the |Coq| printers unless the modifier ``(only
+ much as possible by the Coq printers unless the modifier ``(only
parsing)`` is given.
An abbreviation is bound to an absolute name as an ordinary definition is
@@ -1553,16 +1553,18 @@ numbers (see :ref:`datatypes`).
Number notations
~~~~~~~~~~~~~~~~
-.. cmd:: Number Notation @qualid__type @qualid__parse @qualid__print : @scope_name {? @numeral_modifier }
+.. cmd:: Number Notation @qualid__type @qualid__parse @qualid__print {? ( {+, @number_modifier } ) } : @scope_name
:name: Number Notation
- .. insertprodn numeral_modifier numeral_modifier
+ .. insertprodn number_modifier number_string_via
.. prodn::
- numeral_modifier ::= ( warning after @bignat )
- | ( abstract after @bignat )
+ number_modifier ::= warning after @bignat
+ | abstract after @bignat
+ | @number_string_via
+ number_string_via ::= via @qualid mapping [ {+, {| @qualid => @qualid | [ @qualid ] => @qualid } } ]
- This command allows the user to customize the way numeral literals
+ This command allows the user to customize the way number literals
are parsed and printed.
:n:`@qualid__type`
@@ -1571,32 +1573,32 @@ Number notations
parsing and printing functions, respectively. The parsing function
:n:`@qualid__parse` should have one of the following types:
- * :n:`Numeral.int -> @qualid__type`
- * :n:`Numeral.int -> option @qualid__type`
- * :n:`Numeral.uint -> @qualid__type`
- * :n:`Numeral.uint -> option @qualid__type`
+ * :n:`Number.int -> @qualid__type`
+ * :n:`Number.int -> option @qualid__type`
+ * :n:`Number.uint -> @qualid__type`
+ * :n:`Number.uint -> option @qualid__type`
* :n:`Z -> @qualid__type`
* :n:`Z -> option @qualid__type`
- * :n:`Numeral.numeral -> @qualid__type`
- * :n:`Numeral.numeral -> option @qualid__type`
+ * :n:`Number.number -> @qualid__type`
+ * :n:`Number.number -> option @qualid__type`
And the printing function :n:`@qualid__print` should have one of the
following types:
- * :n:`@qualid__type -> Numeral.int`
- * :n:`@qualid__type -> option Numeral.int`
- * :n:`@qualid__type -> Numeral.uint`
- * :n:`@qualid__type -> option Numeral.uint`
+ * :n:`@qualid__type -> Number.int`
+ * :n:`@qualid__type -> option Number.int`
+ * :n:`@qualid__type -> Number.uint`
+ * :n:`@qualid__type -> option Number.uint`
* :n:`@qualid__type -> Z`
* :n:`@qualid__type -> option Z`
- * :n:`@qualid__type -> Numeral.numeral`
- * :n:`@qualid__type -> option Numeral.numeral`
+ * :n:`@qualid__type -> Number.number`
+ * :n:`@qualid__type -> option Number.number`
.. deprecated:: 8.12
- Numeral notations on :g:`Decimal.uint`, :g:`Decimal.int` and
- :g:`Decimal.decimal` are replaced respectively by numeral
- notations on :g:`Numeral.uint`, :g:`Numeral.int` and
- :g:`Numeral.numeral`.
+ Number notations on :g:`Decimal.uint`, :g:`Decimal.int` and
+ :g:`Decimal.decimal` are replaced respectively by number
+ notations on :g:`Number.uint`, :g:`Number.int` and
+ :g:`Number.number`.
When parsing, the application of the parsing function
:n:`@qualid__parse` to the number will be fully reduced, and universes
@@ -1606,7 +1608,44 @@ Number notations
function application, constructors, inductive type families,
sorts, and primitive integers) will be considered for printing.
- :n:`( warning after @bignat )`
+ .. _number-string-via:
+
+ :n:`via @qualid__ind mapping [ {+, @qualid__constant => @qualid__constructor } ]`
+ When using this option, :n:`@qualid__type` no
+ longer needs to be an inductive type and is instead mapped to the
+ inductive type :n:`@qualid__ind` according to the provided
+ list of pairs, whose first component :n:`@qualid__constant` is a
+ constant of type :n:`@qualid__type`
+ (or a function of type :n:`{* _ -> } @qualid__type`) and the second a
+ constructor of type :n:`@qualid__ind`. The type
+ :n:`@qualid__type` is then replaced by :n:`@qualid__ind` in the
+ above parser and printer types.
+
+ When :n:`@qualid__constant` is surrounded by square brackets,
+ all the implicit arguments of :n:`@qualid__constant` (whether maximally inserted or not) are ignored
+ when translating to :n:`@qualid__constructor` (i.e., before
+ applying :n:`@qualid__print`) and replaced with implicit
+ argument holes :g:`_` when translating from
+ :n:`@qualid__constructor` to :n:`@qualid__constant` (after
+ :n:`@qualid__parse`). See below for an :ref:`example <example-number-notation-implicit-args>`.
+
+ .. note::
+ The implicit status of the arguments is considered
+ only at notation declaration time, any further
+ modification of this status has no impact
+ on the previously declared notations.
+
+ .. note::
+ In case of multiple implicit options (for instance
+ :g:`Arguments eq_refl {A}%type_scope {x}, [_] _`), an
+ argument is considered implicit when it is implicit in any of the
+ options.
+
+ .. note::
+ To use a :token:`sort` as the target type :n:`@qualid__type`, use an :ref:`abbreviation <Abbreviations>`
+ as in the :ref:`example below <example-number-notation-non-inductive>`.
+
+ :n:`warning after @bignat`
displays a warning message about a possible stack
overflow when calling :n:`@qualid__parse` to parse a literal larger than :n:`@bignat`.
@@ -1616,11 +1655,11 @@ Number notations
with :n:`(warning after @bignat)`, this warning is emitted when
parsing a number greater than or equal to :token:`bignat`.
- :n:`( abstract after @bignat )`
+ :n:`abstract after @bignat`
returns :n:`(@qualid__parse m)` when parsing a literal
:n:`m` that's greater than :n:`@bignat` rather than reducing it to a normal form.
Here :g:`m` will be a
- :g:`Numeral.int`, :g:`Numeral.uint`, :g:`Z` or :g:`Numeral.numeral`, depending on the
+ :g:`Number.int`, :g:`Number.uint`, :g:`Z` or :g:`Number.number`, depending on the
type of the parsing function :n:`@qualid__parse`. This allows for a
more compact representation of literals in types such as :g:`nat`,
and limits parse failures due to stack overflow. Note that a
@@ -1634,7 +1673,7 @@ Number notations
with :n:`(abstract after @bignat)`, this warning is emitted when
parsing a number greater than or equal to :token:`bignat`.
Typically, this indicates that the fully computed representation
- of numbers can be so large that non-tail-recursive |OCaml|
+ of numbers can be so large that non-tail-recursive OCaml
functions run out of stack space when trying to walk them.
.. warn:: The 'abstract after' directive has no effect when the parsing function (@qualid__parse) targets an option type.
@@ -1642,76 +1681,94 @@ Number notations
As noted above, the :n:`(abstract after @natural)` directive has no
effect when :n:`@qualid__parse` lands in an :g:`option` type.
+ .. exn:: 'via' and 'abstract' cannot be used together.
+
+ With the :n:`abstract after` option, the parser function
+ :n:`@qualid__parse` does not reduce large numbers to a normal form,
+ which prevents doing the translation given in the :n:`mapping` list.
+
.. exn:: Cannot interpret this number as a value of type @type
- The numeral notation registered for :token:`type` does not support
+ The number notation registered for :token:`type` does not support
the given number. This error is given when the interpretation
function returns :g:`None`, or if the interpretation is registered
only for integers or non-negative integers, and the given number
has a fractional or exponent part or is negative.
- .. exn:: @qualid__parse should go from Numeral.int to @type or (option @type). Instead of Numeral.int, the types Numeral.uint or Z or Int63.int or Numeral.numeral could be used (you may need to require BinNums or Numeral or Int63 first).
+ .. exn:: @qualid__parse should go from Number.int to @type or (option @type). Instead of Number.int, the types Number.uint or Z or Int63.int or Number.number could be used (you may need to require BinNums or Number or Int63 first).
The parsing function given to the :cmd:`Number Notation`
vernacular is not of the right type.
- .. exn:: @qualid__print should go from @type to Numeral.int or (option Numeral.int). Instead of Numeral.int, the types Numeral.uint or Z or Int63.int or Numeral.numeral could be used (you may need to require BinNums or Numeral or Int63 first).
+ .. exn:: @qualid__print should go from @type to Number.int or (option Number.int). Instead of Number.int, the types Number.uint or Z or Int63.int or Number.number could be used (you may need to require BinNums or Number or Int63 first).
The printing function given to the :cmd:`Number Notation`
vernacular is not of the right type.
- .. exn:: Unexpected term @term while parsing a numeral notation.
+ .. exn:: Unexpected term @term while parsing a number notation.
Parsing functions must always return ground terms, made up of
- applications of constructors, inductive types, and primitive
+ function application, constructors, inductive type families, sorts and primitive
integers. Parsing functions may not return terms containing
axioms, bare (co)fixpoints, lambdas, etc.
- .. exn:: Unexpected non-option term @term while parsing a numeral notation.
+ .. exn:: Unexpected non-option term @term while parsing a number notation.
Parsing functions expected to return an :g:`option` must always
return a concrete :g:`Some` or :g:`None` when applied to a
concrete number expressed as a (hexa)decimal. They may not return
opaque constants.
+ .. exn:: Multiple 'via' options.
+
+ At most one :g:`via` option can be given.
+
+ .. exn:: Multiple 'warning after' or 'abstract after' options.
+
+ At most one :g:`warning after` or :g:`abstract after` option can be given.
+
.. _string-notations:
String notations
~~~~~~~~~~~~~~~~
-.. cmd:: String Notation @qualid @qualid__parse @qualid__print : @scope_name
+.. cmd:: String Notation @qualid__type @qualid__parse @qualid__print {? ( @number_string_via ) } : @scope_name
:name: String Notation
Allows the user to customize how strings are parsed and printed.
- The token :n:`@qualid` should be the name of an inductive type,
- while :n:`@qualid__parse` and :n:`@qualid__print` should be the names of the
- parsing and printing functions, respectively. The parsing function
- :n:`@qualid__parse` should have one of the following types:
+ :n:`@qualid__type`
+ the name of an inductive type,
+ while :n:`@qualid__parse` and :n:`@qualid__print` should be the names of the
+ parsing and printing functions, respectively. The parsing function
+ :n:`@qualid__parse` should have one of the following types:
- * :n:`Byte.byte -> @qualid`
- * :n:`Byte.byte -> option @qualid`
- * :n:`list Byte.byte -> @qualid`
- * :n:`list Byte.byte -> option @qualid`
+ * :n:`Byte.byte -> @qualid__type`
+ * :n:`Byte.byte -> option @qualid__type`
+ * :n:`list Byte.byte -> @qualid__type`
+ * :n:`list Byte.byte -> option @qualid__type`
- The printing function :n:`@qualid__print` should have one of the
- following types:
+ The printing function :n:`@qualid__print` should have one of the
+ following types:
- * :n:`@qualid -> Byte.byte`
- * :n:`@qualid -> option Byte.byte`
- * :n:`@qualid -> list Byte.byte`
- * :n:`@qualid -> option (list Byte.byte)`
+ * :n:`@qualid__type -> Byte.byte`
+ * :n:`@qualid__type -> option Byte.byte`
+ * :n:`@qualid__type -> list Byte.byte`
+ * :n:`@qualid__type -> option (list Byte.byte)`
- When parsing, the application of the parsing function
- :n:`@qualid__parse` to the string will be fully reduced, and universes
- of the resulting term will be refreshed.
+ When parsing, the application of the parsing function
+ :n:`@qualid__parse` to the string will be fully reduced, and universes
+ of the resulting term will be refreshed.
- Note that only fully-reduced ground terms (terms containing only
- function application, constructors, inductive type families,
- sorts, and primitive integers) will be considered for printing.
+ Note that only fully-reduced ground terms (terms containing only
+ function application, constructors, inductive type families,
+ sorts, and primitive integers) will be considered for printing.
- .. exn:: Cannot interpret this string as a value of type @type
+ :n:`via @qualid__ind mapping [ {+, @qualid__constant => @qualid__constructor } ]`
+ works as for :ref:`number notations above <number-string-via>`.
+
+ .. exn:: Cannot interpret this string as a value of type @type
The string notation registered for :token:`type` does not support
the given string. This error is given when the interpretation
@@ -1730,7 +1787,7 @@ String notations
.. exn:: Unexpected term @term while parsing a string notation.
Parsing functions must always return ground terms, made up of
- applications of constructors, inductive types, and primitive
+ function application, constructors, inductive type families, sorts and primitive
integers. Parsing functions may not return terms containing
axioms, bare (co)fixpoints, lambdas, etc.
@@ -1741,16 +1798,37 @@ String notations
concrete string expressed as a decimal. They may not return
opaque constants.
-The following errors apply to both string and numeral notations:
+.. note::
+ Number or string notations for parameterized inductive types can be
+ added by declaring an :ref:`abbreviation <Abbreviations>` for the
+ inductive which instantiates all parameters. See :ref:`example below <example-string-notation-parameterized-inductive>`.
+
+The following errors apply to both string and number notations:
.. exn:: @type is not an inductive type.
- String and numeral notations can only be declared for inductive types with no
- arguments.
+ String and number notations can only be declared for inductive types.
+ Declare string or numeral notations for non-inductive types using :n:`@number_string_via`.
+
+ .. exn:: @qualid was already mapped to @qualid and cannot be remapped to @qualid
+
+ Duplicates are not allowed in the :n:`mapping` list.
+
+ .. exn:: Missing mapping for constructor @qualid
+
+ A mapping should be provided for :n:`@qualid` in the :n:`mapping` list.
+
+ .. warn:: @type was already mapped to @type, mapping it also to @type might yield ill typed terms when using the notation.
+
+ Two pairs in the :n:`mapping` list associate types that might be incompatible.
+
+ .. warn:: Type of @qualid seems incompatible with the type of @qualid. Expected type is: @type instead of @type. This might yield ill typed terms when using the notation.
+
+ A mapping given in the :n:`mapping` list associates a constant with a seemingly incompatible constructor.
.. exn:: Cannot interpret in @scope_name because @qualid could not be found in the current environment.
- The inductive type used to register the string or numeral notation is no
+ The inductive type used to register the string or number notation is no
longer available in the environment. Most likely, this is because
the notation was declared inside a functor for an
inductive type inside the functor. This use case is not currently
@@ -1779,6 +1857,198 @@ The following errors apply to both string and numeral notations:
.. todo note on "single qualified identifiers" https://github.com/coq/coq/pull/11718#discussion_r415076703
+.. example:: Number Notation for radix 3
+
+ The following example parses and prints natural numbers
+ whose digits are :g:`0`, :g:`1` or :g:`2` as terms of the following
+ inductive type encoding radix 3 numbers.
+
+ .. coqtop:: in reset
+
+ Inductive radix3 : Set :=
+ | x0 : radix3
+ | x3 : radix3 -> radix3
+ | x3p1 : radix3 -> radix3
+ | x3p2 : radix3 -> radix3.
+
+ We first define a parsing function
+
+ .. coqtop:: in
+
+ Definition of_uint_dec (u : Decimal.uint) : option radix3 :=
+ let fix f u := match u with
+ | Decimal.Nil => Some x0
+ | Decimal.D0 u => match f u with Some u => Some (x3 u) | None => None end
+ | Decimal.D1 u => match f u with Some u => Some (x3p1 u) | None => None end
+ | Decimal.D2 u => match f u with Some u => Some (x3p2 u) | None => None end
+ | _ => None end in
+ f (Decimal.rev u).
+ Definition of_uint (u : Number.uint) : option radix3 :=
+ match u with Number.UIntDecimal u => of_uint_dec u | Number.UIntHexadecimal _ => None end.
+
+ and a printing function
+
+ .. coqtop:: in
+
+ Definition to_uint_dec (x : radix3) : Decimal.uint :=
+ let fix f x := match x with
+ | x0 => Decimal.Nil
+ | x3 x => Decimal.D0 (f x)
+ | x3p1 x => Decimal.D1 (f x)
+ | x3p2 x => Decimal.D2 (f x) end in
+ Decimal.rev (f x).
+ Definition to_uint (x : radix3) : Number.uint := Number.UIntDecimal (to_uint_dec x).
+
+ before declaring the notation
+
+ .. coqtop:: in
+
+ Declare Scope radix3_scope.
+ Open Scope radix3_scope.
+ Number Notation radix3 of_uint to_uint : radix3_scope.
+
+ We can check the printer
+
+ .. coqtop:: all
+
+ Check x3p2 (x3p1 x0).
+
+ and the parser
+
+ .. coqtop:: all
+
+ Set Printing All.
+ Check 120.
+
+ Digits other than :g:`0`, :g:`1` and :g:`2` are rejected.
+
+ .. coqtop:: all fail
+
+ Check 3.
+
+.. _example-number-notation-non-inductive:
+
+.. example:: Number Notation for a non inductive type
+
+ The following example encodes the terms in the form :g:`sum unit ( ... (sum unit unit) ... )`
+ as the number of units in the term. For instance :g:`sum unit (sum unit unit)`
+ is encoded as :g:`3` while :g:`unit` is :g:`1` and :g:`0` stands for :g:`Empty_set`.
+ The inductive :g:`I` will be used as :n:`@qualid__ind`.
+
+ .. coqtop:: in reset
+
+ Inductive I := Iempty : I | Iunit : I | Isum : I -> I -> I.
+
+ We then define :n:`@qualid__parse` and :n:`@qualid__print`
+
+ .. coqtop:: in
+
+ Definition of_uint (x : Number.uint) : I :=
+ let fix f n := match n with
+ | O => Iempty | S O => Iunit
+ | S n => Isum Iunit (f n) end in
+ f (Nat.of_num_uint x).
+
+ Definition to_uint (x : I) : Number.uint :=
+ let fix f i := match i with
+ | Iempty => O | Iunit => 1
+ | Isum i1 i2 => f i1 + f i2 end in
+ Nat.to_num_uint (f x).
+
+ Inductive sum (A : Set) (B : Set) : Set := pair : A -> B -> sum A B.
+
+ the number notation itself
+
+ .. coqtop:: in
+
+ Notation nSet := Set (only parsing).
+ Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum]) : type_scope.
+
+ and check the printer
+
+ .. coqtop:: all
+
+ Local Open Scope type_scope.
+ Check sum unit (sum unit unit).
+
+ and the parser
+
+ .. coqtop:: all
+
+ Set Printing All.
+ Check 3.
+
+.. _example-number-notation-implicit-args:
+
+.. example:: Number Notation with implicit arguments
+
+ The following example parses and prints natural numbers between
+ :g:`0` and :g:`n-1` as terms of type :g:`Fin.t n`.
+
+ .. coqtop:: all reset
+
+ Require Import Vector.
+ Print Fin.t.
+
+ Note the implicit arguments of :g:`Fin.F1` and :g:`Fin.FS`,
+ which won't appear in the corresponding inductive type.
+
+ .. coqtop:: in
+
+ Inductive I := I1 : I | IS : I -> I.
+
+ Definition of_uint (x : Number.uint) : I :=
+ let fix f n := match n with O => I1 | S n => IS (f n) end in
+ f (Nat.of_num_uint x).
+
+ Definition to_uint (x : I) : Number.uint :=
+ let fix f i := match i with I1 => O | IS n => S (f n) end in
+ Nat.to_num_uint (f x).
+
+ Declare Scope fin_scope.
+ Delimit Scope fin_scope with fin.
+ Local Open Scope fin_scope.
+ Number Notation Fin.t of_uint to_uint (via I
+ mapping [[Fin.F1] => I1, [Fin.FS] => IS]) : fin_scope.
+
+ Now :g:`2` is parsed as :g:`Fin.FS (Fin.FS Fin.F1)`, that is
+ :g:`@Fin.FS _ (@Fin.FS _ (@Fin.F1 _))`.
+
+ .. coqtop:: all
+
+ Check 2.
+
+ which can be of type :g:`Fin.t 3` (numbers :g:`0`, :g:`1` and :g:`2`)
+
+ .. coqtop:: all
+
+ Check 2 : Fin.t 3.
+
+ but cannot be of type :g:`Fin.t 2` (only :g:`0` and :g:`1`)
+
+ .. coqtop:: all fail
+
+ Check 2 : Fin.t 2.
+
+.. _example-string-notation-parameterized-inductive:
+
+.. example:: String Notation with a parameterized inductive type
+
+ The parameter :g:`Byte.byte` for the parameterized inductive type
+ :g:`list` is given through an :ref:`abbreviation <Abbreviations>`.
+
+ .. coqtop:: in reset
+
+ Notation string := (list Byte.byte) (only parsing).
+ Definition id_string := @id string.
+
+ String Notation string id_string id_string : list_scope.
+
+ .. coqtop:: all
+
+ Check "abc"%list.
+
.. _TacticNotation:
Tactic Notations
@@ -1978,9 +2248,9 @@ Tactic notations allow customizing the syntax of tactics.
.. rubric:: Footnotes
.. [#and_or_levels] which are the levels effectively chosen in the current
- implementation of |Coq|
+ implementation of Coq
-.. [#no_associativity] |Coq| accepts notations declared as nonassociative but the parser on
- which |Coq| is built, namely Camlp5, currently does not implement ``no associativity`` and
- replaces it with ``left associativity``; hence it is the same for |Coq|: ``no associativity``
+.. [#no_associativity] Coq accepts notations declared as nonassociative but the parser on
+ which Coq is built, namely Camlp5, currently does not implement ``no associativity`` and
+ replaces it with ``left associativity``; hence it is the same for Coq: ``no associativity``
is in fact ``left associativity`` for the purposes of parsing
diff --git a/doc/sphinx/using/libraries/index.rst b/doc/sphinx/using/libraries/index.rst
index 95218322ff..0bd3054788 100644
--- a/doc/sphinx/using/libraries/index.rst
+++ b/doc/sphinx/using/libraries/index.rst
@@ -4,15 +4,15 @@
Libraries and plugins
=====================
-|Coq| is distributed with a standard library and a set of internal
+Coq is distributed with a standard library and a set of internal
plugins (most of which provide tactics that have already been
presented in :ref:`writing-proofs`). This chapter presents this
standard library and some of these internal plugins which provide
features that are not tactics.
-In addition, |Coq| has a rich ecosystem of external libraries and
+In addition, Coq has a rich ecosystem of external libraries and
plugins. These libraries and plugins can be browsed online through
-the `|Coq| Package Index <https://coq.inria.fr/opam/www/>`_ and
+the `Coq Package Index <https://coq.inria.fr/opam/www/>`_ and
installed with the `opam package manager
<https://coq.inria.fr/opam-using.html>`_.
diff --git a/doc/sphinx/using/libraries/writing.rst b/doc/sphinx/using/libraries/writing.rst
index 724bcd0488..917edf0774 100644
--- a/doc/sphinx/using/libraries/writing.rst
+++ b/doc/sphinx/using/libraries/writing.rst
@@ -1,9 +1,9 @@
-Writing |Coq| libraries and plugins
+Writing Coq libraries and plugins
===================================
-This section presents the part of the |Coq| language that is useful only
-to library and plugin authors. A tutorial for writing |Coq| plugins is
-available in the |Coq| repository in `doc/plugin_tutorial
+This section presents the part of the Coq language that is useful only
+to library and plugin authors. A tutorial for writing Coq plugins is
+available in the Coq repository in `doc/plugin_tutorial
<https://github.com/coq/coq/tree/master/doc/plugin_tutorial>`_.
Deprecating library objects or tactics
diff --git a/doc/sphinx/using/tools/coqdoc.rst b/doc/sphinx/using/tools/coqdoc.rst
index 88c1a575d9..7ab8f9d763 100644
--- a/doc/sphinx/using/tools/coqdoc.rst
+++ b/doc/sphinx/using/tools/coqdoc.rst
@@ -2,14 +2,14 @@
.. _coqdoc:
-Documenting |Coq| files with coqdoc
+Documenting Coq files with coqdoc
-----------------------------------
-coqdoc is a documentation tool for the proof assistant |Coq|, similar to
+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,
+#. 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.
@@ -18,9 +18,9 @@ coqdoc is a documentation tool for the proof assistant |Coq|, similar to
Principles
~~~~~~~~~~
-Documentation is inserted into |Coq| files as *special comments*. Thus
+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
+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
@@ -29,10 +29,10 @@ shouldn’t fail, whatever the input is. But remember: “garbage in,
garbage out”.
-|Coq| material inside documentation.
+Coq material inside documentation.
++++++++++++++++++++++++++++++++++++
-|Coq| material is quoted between the delimiters ``[`` and ``]``. Square brackets
+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
@@ -46,7 +46,7 @@ Pretty-printing.
++++++++++++++++
coqdoc uses different faces for identifiers and keywords. The pretty-
-printing of |Coq| tokens (identifiers or symbols) can be controlled
+printing of Coq tokens (identifiers or symbols) can be controlled
using one of the following commands:
::
@@ -63,7 +63,7 @@ or
(** printing *token* $...LATEX math...$ #...html...# *)
-It gives the |Latex| and HTML texts to be produced for the given |Coq|
+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.
@@ -91,7 +91,7 @@ commands.
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
+ 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.
@@ -217,7 +217,7 @@ 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
+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.
@@ -253,7 +253,7 @@ The latter cannot be used around some inner parts of a proof, but can
be used around a whole proof.
Lastly, it is possible to adopt a middle-ground approach when the
-desired output is HTML, where a given snippet of |Coq| material is
+desired output is HTML, where a given snippet of Coq material is
hidden by default, but can be made visible with user interaction.
::
@@ -280,12 +280,12 @@ 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
+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
+ 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
@@ -295,7 +295,7 @@ suffixes ``.v`` and ``.g`` and |Latex| files by the suffix ``.tex``.
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.
+ to be used by the TEXmacs Coq interface.
@@ -357,18 +357,18 @@ Command line options
**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.
+ :--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
+ :--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``).
+ :-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::
@@ -420,7 +420,7 @@ Command line options
:--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.
+ identifiers appearing in Coq escapings inside comments.
**Language options**
diff --git a/doc/sphinx/using/tools/index.rst b/doc/sphinx/using/tools/index.rst
index 8543c5de8a..dfe38dfce9 100644
--- a/doc/sphinx/using/tools/index.rst
+++ b/doc/sphinx/using/tools/index.rst
@@ -5,11 +5,11 @@ Command-line and graphical tools
================================
This chapter presents the command-line tools that users will need to
-build their |Coq| project, the documentation of the |CoqIDE| standalone
+build their Coq project, the documentation of the CoqIDE standalone
user interface and the documentation of the parallel proof processing
-feature that is supported by |CoqIDE| and several other user interfaces.
-A list of available user interfaces to interact with |Coq| is available
-on the `|Coq| website <https://coq.inria.fr/user-interfaces.html>`_.
+feature that is supported by CoqIDE and several other user interfaces.
+A list of available user interfaces to interact with Coq is available
+on the `Coq website <https://coq.inria.fr/user-interfaces.html>`_.
.. toctree::
:maxdepth: 1
diff --git a/doc/stdlib/hidden-files b/doc/stdlib/hidden-files
index 4d2972ef8f..e4f0967794 100644
--- a/doc/stdlib/hidden-files
+++ b/doc/stdlib/hidden-files
@@ -1,3 +1,4 @@
+theories/Init/Numeral.v
theories/btauto/Algebra.v
theories/btauto/Btauto.v
theories/btauto/Reflect.v
diff --git a/doc/stdlib/index-list.html.template b/doc/stdlib/index-list.html.template
index 7c1328916b..7201dc6a0e 100644
--- a/doc/stdlib/index-list.html.template
+++ b/doc/stdlib/index-list.html.template
@@ -22,7 +22,7 @@ through the <tt>Require Import</tt> command.</p>
theories/Init/Nat.v
theories/Init/Decimal.v
theories/Init/Hexadecimal.v
- theories/Init/Numeral.v
+ theories/Init/Number.v
theories/Init/Peano.v
theories/Init/Specif.v
theories/Init/Tactics.v
@@ -238,6 +238,7 @@ through the <tt>Require Import</tt> command.</p>
theories/Numbers/DecimalN.v
theories/Numbers/DecimalZ.v
theories/Numbers/DecimalQ.v
+ theories/Numbers/DecimalR.v
theories/Numbers/DecimalString.v
theories/Numbers/HexadecimalFacts.v
theories/Numbers/HexadecimalNat.v
@@ -245,6 +246,7 @@ through the <tt>Require Import</tt> command.</p>
theories/Numbers/HexadecimalN.v
theories/Numbers/HexadecimalZ.v
theories/Numbers/HexadecimalQ.v
+ theories/Numbers/HexadecimalR.v
theories/Numbers/HexadecimalString.v
</dd>
@@ -704,7 +706,6 @@ through the <tt>Require Import</tt> command.</p>
</dt>
<dd>
theories/Compat/AdmitAxiom.v
- theories/Compat/Coq810.v
theories/Compat/Coq811.v
theories/Compat/Coq812.v
theories/Compat/Coq813.v
diff --git a/doc/tools/coqrst/notations/TacticNotations.g b/doc/tools/coqrst/notations/TacticNotations.g
index f29c69eeaf..70107eba46 100644
--- a/doc/tools/coqrst/notations/TacticNotations.g
+++ b/doc/tools/coqrst/notations/TacticNotations.g
@@ -43,7 +43,8 @@ LGROUP: '{+' | '{*' | '{?';
LBRACE: '{';
RBRACE: '}';
// todo: need a cleaner way to escape the 3-character strings here
-ESCAPED: '%{' | '%}' | '%|' | '`%{' | '@%{';
+ESCAPED: '%{' | '%}' | '%|' | '`%{' | '@%{' |
+ '%|-' | '%|->' | '%||' | '%|||' | '%||||'; // for SSR
PIPE: '|';
ATOM: '@' | '_' | ~[@_{}| ]+;
ID: '@' ('_'? [a-zA-Z0-9])+;
diff --git a/doc/tools/coqrst/notations/TacticNotationsLexer.py b/doc/tools/coqrst/notations/TacticNotationsLexer.py
index 7bda849010..a7ad55ad34 100644
--- a/doc/tools/coqrst/notations/TacticNotationsLexer.py
+++ b/doc/tools/coqrst/notations/TacticNotationsLexer.py
@@ -8,35 +8,40 @@ import sys
def serializedATN():
with StringIO() as buf:
buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\f")
- buf.write("S\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7")
+ buf.write("f\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7")
buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\3\2\3\2\3\2\3\3\3\3")
buf.write("\3\3\3\3\3\3\3\3\5\3!\n\3\3\4\3\4\3\5\3\5\3\6\3\6\3\6")
- buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6\63\n\6\3\7\3")
- buf.write("\7\3\b\3\b\6\b9\n\b\r\b\16\b:\5\b=\n\b\3\t\3\t\5\tA\n")
- buf.write("\t\3\t\6\tD\n\t\r\t\16\tE\3\n\3\n\3\n\6\nK\n\n\r\n\16")
- buf.write("\nL\3\13\6\13P\n\13\r\13\16\13Q\2\2\f\3\3\5\4\7\5\t\6")
- buf.write("\13\7\r\b\17\t\21\n\23\13\25\f\3\2\5\4\2BBaa\6\2\"\"B")
- buf.write("Baa}\177\5\2\62;C\\c|\2^\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3")
- buf.write("\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2")
- buf.write("\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\3\27\3\2\2\2")
- buf.write("\5 \3\2\2\2\7\"\3\2\2\2\t$\3\2\2\2\13\62\3\2\2\2\r\64")
- buf.write("\3\2\2\2\17<\3\2\2\2\21>\3\2\2\2\23G\3\2\2\2\25O\3\2\2")
- buf.write("\2\27\30\7}\2\2\30\31\7~\2\2\31\4\3\2\2\2\32\33\7}\2\2")
- buf.write("\33!\7-\2\2\34\35\7}\2\2\35!\7,\2\2\36\37\7}\2\2\37!\7")
- buf.write("A\2\2 \32\3\2\2\2 \34\3\2\2\2 \36\3\2\2\2!\6\3\2\2\2\"")
- buf.write("#\7}\2\2#\b\3\2\2\2$%\7\177\2\2%\n\3\2\2\2&\'\7\'\2\2")
- buf.write("\'\63\7}\2\2()\7\'\2\2)\63\7\177\2\2*+\7\'\2\2+\63\7~")
- buf.write("\2\2,-\7b\2\2-.\7\'\2\2.\63\7}\2\2/\60\7B\2\2\60\61\7")
- buf.write("\'\2\2\61\63\7}\2\2\62&\3\2\2\2\62(\3\2\2\2\62*\3\2\2")
- buf.write("\2\62,\3\2\2\2\62/\3\2\2\2\63\f\3\2\2\2\64\65\7~\2\2\65")
- buf.write("\16\3\2\2\2\66=\t\2\2\2\679\n\3\2\28\67\3\2\2\29:\3\2")
- buf.write("\2\2:8\3\2\2\2:;\3\2\2\2;=\3\2\2\2<\66\3\2\2\2<8\3\2\2")
- buf.write("\2=\20\3\2\2\2>C\7B\2\2?A\7a\2\2@?\3\2\2\2@A\3\2\2\2A")
- buf.write("B\3\2\2\2BD\t\4\2\2C@\3\2\2\2DE\3\2\2\2EC\3\2\2\2EF\3")
- buf.write("\2\2\2F\22\3\2\2\2GH\7a\2\2HJ\7a\2\2IK\t\4\2\2JI\3\2\2")
- buf.write("\2KL\3\2\2\2LJ\3\2\2\2LM\3\2\2\2M\24\3\2\2\2NP\7\"\2\2")
- buf.write("ON\3\2\2\2PQ\3\2\2\2QO\3\2\2\2QR\3\2\2\2R\26\3\2\2\2\13")
- buf.write("\2 \62:<@ELQ\2")
+ buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3")
+ buf.write("\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6")
+ buf.write("\3\6\5\6F\n\6\3\7\3\7\3\b\3\b\6\bL\n\b\r\b\16\bM\5\bP")
+ buf.write("\n\b\3\t\3\t\5\tT\n\t\3\t\6\tW\n\t\r\t\16\tX\3\n\3\n\3")
+ buf.write("\n\6\n^\n\n\r\n\16\n_\3\13\6\13c\n\13\r\13\16\13d\2\2")
+ buf.write("\f\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\3\2\5")
+ buf.write("\4\2BBaa\6\2\"\"BBaa}\177\5\2\62;C\\c|\2v\2\3\3\2\2\2")
+ buf.write("\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r")
+ buf.write("\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3")
+ buf.write("\2\2\2\3\27\3\2\2\2\5 \3\2\2\2\7\"\3\2\2\2\t$\3\2\2\2")
+ buf.write("\13E\3\2\2\2\rG\3\2\2\2\17O\3\2\2\2\21Q\3\2\2\2\23Z\3")
+ buf.write("\2\2\2\25b\3\2\2\2\27\30\7}\2\2\30\31\7~\2\2\31\4\3\2")
+ buf.write("\2\2\32\33\7}\2\2\33!\7-\2\2\34\35\7}\2\2\35!\7,\2\2\36")
+ buf.write("\37\7}\2\2\37!\7A\2\2 \32\3\2\2\2 \34\3\2\2\2 \36\3\2")
+ buf.write("\2\2!\6\3\2\2\2\"#\7}\2\2#\b\3\2\2\2$%\7\177\2\2%\n\3")
+ buf.write("\2\2\2&\'\7\'\2\2\'F\7}\2\2()\7\'\2\2)F\7\177\2\2*+\7")
+ buf.write("\'\2\2+F\7~\2\2,-\7b\2\2-.\7\'\2\2.F\7}\2\2/\60\7B\2\2")
+ buf.write("\60\61\7\'\2\2\61F\7}\2\2\62\63\7\'\2\2\63\64\7~\2\2\64")
+ buf.write("F\7/\2\2\65\66\7\'\2\2\66\67\7~\2\2\678\7/\2\28F\7@\2")
+ buf.write("\29:\7\'\2\2:;\7~\2\2;F\7~\2\2<=\7\'\2\2=>\7~\2\2>?\7")
+ buf.write("~\2\2?F\7~\2\2@A\7\'\2\2AB\7~\2\2BC\7~\2\2CD\7~\2\2DF")
+ buf.write("\7~\2\2E&\3\2\2\2E(\3\2\2\2E*\3\2\2\2E,\3\2\2\2E/\3\2")
+ buf.write("\2\2E\62\3\2\2\2E\65\3\2\2\2E9\3\2\2\2E<\3\2\2\2E@\3\2")
+ buf.write("\2\2F\f\3\2\2\2GH\7~\2\2H\16\3\2\2\2IP\t\2\2\2JL\n\3\2")
+ buf.write("\2KJ\3\2\2\2LM\3\2\2\2MK\3\2\2\2MN\3\2\2\2NP\3\2\2\2O")
+ buf.write("I\3\2\2\2OK\3\2\2\2P\20\3\2\2\2QV\7B\2\2RT\7a\2\2SR\3")
+ buf.write("\2\2\2ST\3\2\2\2TU\3\2\2\2UW\t\4\2\2VS\3\2\2\2WX\3\2\2")
+ buf.write("\2XV\3\2\2\2XY\3\2\2\2Y\22\3\2\2\2Z[\7a\2\2[]\7a\2\2\\")
+ buf.write("^\t\4\2\2]\\\3\2\2\2^_\3\2\2\2_]\3\2\2\2_`\3\2\2\2`\24")
+ buf.write("\3\2\2\2ac\7\"\2\2ba\3\2\2\2cd\3\2\2\2db\3\2\2\2de\3\2")
+ buf.write("\2\2e\26\3\2\2\2\13\2 EMOSX_d\2")
return buf.getvalue()
diff --git a/doc/tools/docgram/README.md b/doc/tools/docgram/README.md
index dbb04bb6a6..6c507e1d57 100644
--- a/doc/tools/docgram/README.md
+++ b/doc/tools/docgram/README.md
@@ -179,6 +179,8 @@ grammar with its productions and removing the non-terminal. Each should appear
as a separate production. (Doesn't work recursively; splicing for both
`A: [ | B ]` and `B: [ | C ]` must be done in separate SPLICE operations.)
+`OPTINREF` - applies the local `OPTINREF` edit to every nonterminal
+
`EXPAND` - expands LIST0, LIST1, LIST* ... SEP and OPT constructs into
new non-terminals
diff --git a/doc/tools/docgram/common.edit_mlg b/doc/tools/docgram/common.edit_mlg
index f6a684bbd7..4c1956d172 100644
--- a/doc/tools/docgram/common.edit_mlg
+++ b/doc/tools/docgram/common.edit_mlg
@@ -19,7 +19,8 @@ lglob: [
]
hint: [
-| "Extern" natural OPT constr_pattern "=>" tactic
+| REPLACE "Extern" natural OPT Constr.constr_pattern "=>" Pltac.tactic
+| WITH "Extern" natural OPT constr_pattern "=>" tactic
]
(* todo: does ARGUMENT EXTEND make the symbol global? It is in both extraargs and extratactics *)
@@ -28,19 +29,12 @@ strategy_level_or_var: [
| strategy_level
]
-term0: [
-| "ltac" ":" "(" ltac_expr5 ")"
-]
-
EXTRAARGS_natural: [ | DELETENT ]
EXTRAARGS_lconstr: [ | DELETENT ]
EXTRAARGS_strategy_level: [ | DELETENT ]
-G_LTAC_hint: [ | DELETENT ]
-G_LTAC_term0: [ | DELETENT ]
-G_REWRITE_binders: [
+binders: [
| DELETE Pcoq.Constr.binders
-| binders
]
G_TACTIC_in_clause: [
@@ -50,7 +44,6 @@ G_TACTIC_in_clause: [
]
SPLICE: [
-| G_REWRITE_binders
| G_TACTIC_in_clause
]
@@ -92,6 +85,7 @@ RENAME: [
| G_LTAC2_as_ipat ltac2_as_ipat
| G_LTAC2_by_tactic ltac2_by_tactic
| G_LTAC2_match_list ltac2_match_list
+| G_SSRMATCHING_cpattern ssr_one_term_pattern
]
(* Renames to eliminate qualified names.
@@ -112,13 +106,14 @@ RENAME: [
| Prim.natural natural
| Pvernac.Vernac_.main_entry vernac_control
| Tactic.tactic tactic
+| Pltac.ltac_expr ltac_expr5
(* SSR *)
+| Pcoq.Constr.constr term
+| Prim.identref ident
(*
| G_vernac.def_body def_body
-| Pcoq.Constr.constr term
| Prim.by_notation by_notation
-| Prim.identref ident
| Prim.natural natural
*)
| Vernac.fix_definition fix_definition
@@ -156,11 +151,16 @@ DELETE: [
| test_array_closing
(* SSR *)
-(* | ssr_null_entry *)
-(*
+| ssr_null_entry
| ssrtermkind (* todo: rename as "test..." *)
-| term_annotation (* todo: rename as "test..." *)
+| ssrdoarg (* todo: this and the next one should be removed from the grammar? *)
+| ssrseqdir
+| ssrindex
+| ssrintrosarg
+| ssrtclarg
+| term_annotation (* todo: what is this? *)
| test_idcomma
+| test_ident_no_do
| test_nohidden
| test_not_ssrslashnum
| test_ssr_rw_syntax
@@ -171,10 +171,6 @@ DELETE: [
| test_ssrslashnum01
| test_ssrslashnum10
| test_ssrslashnum11
-| test_ident_no_do
-| ssrdoarg (* todo: this and the next one should be removed from the grammar? *)
-| ssrseqdir
-*)
(* unused *)
| constr_comma_sequence'
@@ -182,8 +178,6 @@ DELETE: [
| constr_may_eval
]
-(* ssrintrosarg: [ | DELETENT ] *)
-
(* additional nts to be spliced *)
tactic_then_last: [
@@ -202,10 +196,6 @@ for_each_goal: [
| OPT ( goal_tactics "|" ) OPT ltac_expr5 ".." OPT ( "|" goal_tactics )
]
-tactic_then_last: [
-| OPTINREF
-]
-
ltac2_tactic_then_last: [
| REPLACE "|" LIST0 ( OPT ltac2_expr6 ) SEP "|" (* Ltac2 plugin *)
| WITH LIST0 ( "|" OPT ltac2_expr6 ) TAG Ltac2
@@ -222,10 +212,6 @@ ltac2_for_each_goal: [
| OPT ( ltac2_goal_tactics "|" ) OPT ltac2_expr6 ".." OPT ( "|" ltac2_goal_tactics ) TAG Ltac2
]
-ltac2_tactic_then_last: [
-| OPTINREF
-]
-
reference: [ | DELETENT ]
reference: [
@@ -270,7 +256,18 @@ binder_constr: [
| MOVETO term_forall_or_fun "forall" open_binders "," term200
| MOVETO term_forall_or_fun "fun" open_binders "=>" term200
| MOVETO term_let "let" name binders let_type_cstr ":=" term200 "in" term200
+(*| MOVETO term_let "let" ":" ssr_mpat ":=" lconstr "in" lconstr TAG SSR *)
+| DELETE "let" ":" ssr_mpat ":=" lconstr "in" lconstr TAG SSR (* todo: restore for ssr *)
+| REPLACE "let" ":" ssr_mpat "in" pattern200 ":=" lconstr ssr_rtype "in" lconstr (* ssr plugin *)
+| WITH "let" ":" ssr_mpat OPT ( "in" pattern200 ) ":=" lconstr ssr_rtype "in" lconstr TAG SSR
+| DELETE "let" ":" ssr_mpat ":=" lconstr ssr_rtype "in" lconstr (* SSR plugin *)
+| DELETE "let" ":" ssr_mpat OPT ( "in" pattern200 ) ":=" lconstr ssr_rtype "in" lconstr TAG SSR (* todo: restore for SSR *)
+(*| MOVETO term_let "let" ":" ssr_mpat OPT ( "in" pattern200 ) ":=" lconstr ssr_rtype "in" lconstr TAG SSR*)
| MOVETO term_if "if" term200 as_return_type "then" term200 "else" term200
+| REPLACE "if" term200 "is" ssr_dthen ssr_else
+| WITH "if" term200 [ "is" | "isn't" ] ssr_dthen ssr_else TAG SSR
+| DELETE "if" term200 "isn't" ssr_dthen ssr_else
+| DELETE "if" term200 [ "is" | "isn't" ] ssr_dthen ssr_else TAG SSR (* todo: restore for SSR *)
| MOVETO term_fix "let" "fix" fix_decl "in" term200
| MOVETO term_cofix "let" "cofix" cofix_body "in" term200
| MOVETO term_let "let" [ "(" LIST0 name SEP "," ")" | "()" ] as_return_type ":=" term200 "in" term200
@@ -288,9 +285,12 @@ term_let: [
(* Don't need to document that "( )" is equivalent to "()" *)
| REPLACE "let" [ "(" LIST0 name SEP "," ")" | "()" ] as_return_type ":=" term200 "in" term200
| WITH "let" "(" LIST0 name SEP "," ")" as_return_type ":=" term200 "in" term200
+| MOVETO destructuring_let "let" "(" LIST0 name SEP "," ")" as_return_type ":=" term200 "in" term200
| REPLACE "let" "'" pattern200 ":=" term200 "in" term200
-| WITH "let" "'" pattern200 ":=" term200 OPT case_type "in" term200
+| WITH "let" "'" pattern200 ":=" term200 OPT case_type "in" term200
| DELETE "let" "'" pattern200 ":=" term200 case_type "in" term200
+| MOVETO destructuring_let "let" "'" pattern200 ":=" term200 OPT case_type "in" term200
+| MOVETO destructuring_let "let" "'" pattern200 "in" pattern200 ":=" term200 case_type "in" term200
]
atomic_constr: [
@@ -310,6 +310,7 @@ atomic_constr: [
ltac_expr0: [
| REPLACE "[" ">" for_each_goal "]"
| WITH "[>" for_each_goal "]"
+| DELETE ssrparentacarg
]
(* lexer token *)
@@ -473,6 +474,7 @@ closed_binder: [
| MOVETO generalizing_binder "`(" LIST1 typeclass_constraint SEP "," ")"
| MOVETO generalizing_binder "`{" LIST1 typeclass_constraint SEP "," "}"
| MOVETO generalizing_binder "`[" LIST1 typeclass_constraint SEP "," "]"
+| DELETE [ "of" | "&" ] term99 (* todo: remove for SSR *)
]
name_colon: [
@@ -530,14 +532,6 @@ eqn: [
| WITH LIST1 [ LIST1 pattern100 SEP "," ] SEP "|" "=>" lconstr
]
-universe_increment: [
-| OPTINREF
-]
-
-evar_instance: [
-| OPTINREF
-]
-
(* No constructor syntax, OPT [ "|" binders ] is not supported for Record *)
record_definition: [
| opt_coercion ident_decl binders OPT [ ":" sort ] OPT ( ":=" OPT [ identref ] "{" record_fields "}" )
@@ -581,10 +575,6 @@ finite_token: [
| DELETENT
]
-constructors_or_record: [
-| OPTINREF
-]
-
record_fields: [
| REPLACE record_field ";" record_fields
| WITH LIST0 record_field SEP ";" OPT ";"
@@ -600,11 +590,6 @@ inline: [
| REPLACE "Inline" "(" natural ")"
| WITH "Inline" OPT ( "(" natural ")" )
| DELETE "Inline"
-| OPTINREF
-]
-
-univ_annot: [
-| OPTINREF
]
univ_decl: [
@@ -620,10 +605,6 @@ of_type: [
| [ ":" | ":>" ] type
]
-attr_value: [
-| OPTINREF
-]
-
def_body: [
| DELETE binders ":=" reduce lconstr
| REPLACE binders ":" lconstr ":=" reduce lconstr
@@ -632,14 +613,6 @@ def_body: [
| WITH LIST0 binder ":" type
]
-reduce: [
-| OPTINREF
-]
-
-occs: [
-| OPTINREF
-]
-
delta_flag: [
| REPLACE "-" "[" LIST1 smart_global "]"
| WITH OPT "-" "[" LIST1 smart_global "]"
@@ -653,7 +626,6 @@ ltac2_delta_flag: [
ltac2_branches: [
| EDIT ADD_OPT "|" LIST1 branch SEP "|" (* Ltac2 plugin *)
-| OPTINREF
]
strategy_flag: [
@@ -662,7 +634,6 @@ strategy_flag: [
(*| REPLACE LIST1 red_flags
| WITH LIST1 red_flag*)
| (* empty *)
-| OPTINREF
]
filtered_import: [
@@ -671,20 +642,14 @@ filtered_import: [
| DELETE global
]
-functor_app_annot: [
-| OPTINREF
-]
-
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: [
@@ -729,10 +694,6 @@ gallina_ext: [
| WITH "From" dirpath "Require" export_token LIST1 global
]
-export_token: [
-| OPTINREF
-]
-
(* lexer stuff *)
LEFTQMARK: [
| "?"
@@ -785,6 +746,7 @@ subsequent_letter: [
ident: [
| DELETE IDENT
+| DELETE IDENT (* 2nd copy from SSR *)
| first_letter LIST0 subsequent_letter
]
@@ -840,6 +802,10 @@ ltac_expr4: [
| REPLACE ltac_expr3 ";" binder_tactic
| WITH ltac_expr3 ";" [ ltac_expr3 | binder_tactic ]
| DELETE ltac_expr3 ";" ltac_expr3
+| MOVETO simple_tactic ltac_expr5 ";" "first" ssr_first_else TAG SSR
+| MOVETO simple_tactic ltac_expr5 ";" "first" ssrseqarg TAG SSR
+| MOVETO simple_tactic ltac_expr5 ";" "last" ssrseqarg TAG SSR
+| DELETE simple_tactic
]
l3_tactic: [ ]
@@ -849,6 +815,7 @@ ltac_expr3: [
| REPLACE "abstract" ltac_expr2 "using" ident
| WITH "abstract" ltac_expr2 OPT ( "using" ident )
| l3_tactic
+| EDIT "do" ADD_OPT int_or_var ssrmmod ssrdotac ssrclauses TAG SSR
| MOVEALLBUT ltac_builtins
| l3_tactic
| ltac_expr2
@@ -1105,6 +1072,43 @@ simple_tactic: [
(* in Tactic Notation: *)
| "setoid_replace" constr "with" constr OPT ( "using" "relation" constr ) OPT ( "in" hyp )
OPT ( "at" LIST1 int_or_var ) OPT ( "by" ltac_expr3 )
+| REPLACE "apply" ssrapplyarg (* SSR plugin *)
+| WITH "apply" OPT ssrapplyarg TAG SSR
+| DELETE "apply"
+| REPLACE "elim" ssrarg ssrclauses (* SSR plugin *)
+| WITH "elim" OPT ( ssrarg ssrclauses ) TAG SSR
+| DELETE "elim" (* SSR plugin *)
+| REPLACE "case" ssrcasearg ssrclauses (* SSR plugin *)
+| WITH "case" OPT ( ssrcasearg ssrclauses ) TAG SSR
+| DELETE "case" (* SSR plugin *)
+| REPLACE "under" ssrrwarg ssrintros_ne "do" ssrhint3arg (* SSR plugin *)
+| WITH "under" ssrrwarg OPT ssrintros_ne OPT ( "do" ssrhint3arg ) TAG SSR
+| DELETE "under" ssrrwarg (* SSR plugin *)
+| DELETE "under" ssrrwarg ssrintros_ne (* SSR plugin *)
+| DELETE "under" ssrrwarg "do" ssrhint3arg (* SSR plugin *)
+| REPLACE "move" ssrmovearg ssrrpat (* SSR plugin *)
+| WITH "move" OPT ( OPT ssrmovearg ssrrpat ) TAG SSR
+| DELETE "move" ssrrpat (* SSR plugin *)
+| DELETE "move" (* SSR plugin *)
+| REPLACE "suff" "have" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| WITH [ "suff" | "suffices" ] OPT ( "have" ssrhpats_nobs ) ssrhavefwd TAG SSR
+| DELETE "suffices" "have" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| REPLACE "suff" ssrsufffwd (* SSR plugin *)
+| WITH [ "suff" | "suffices" ] ssrsufffwd TAG SSR
+| DELETE "suffices" ssrsufffwd (* SSR plugin *)
+| REPLACE "have" "suff" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| WITH "have" [ "suff" | "suffices" ] ssrhpats_nobs ssrhavefwd TAG SSR
+| DELETE "have" "suffices" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| REPLACE "gen" "have" ssrclear ssr_idcomma ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| WITH [ "gen" | "generally" ] "have" ssrclear ssr_idcomma ssrhpats_nobs ssrwlogfwd ssrhint TAG SSR
+| DELETE "generally" "have" ssrclear ssr_idcomma ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| REPLACE "wlog" "suff" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| WITH [ "wlog" | "without loss" ] OPT [ "suff" | "suffices" ] ssrhpats_nobs ssrwlogfwd ssrhint TAG SSR
+| DELETE "wlog" "suffices" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| DELETE "wlog" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| DELETE "without" "loss" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| DELETE "without" "loss" "suff" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| DELETE "without" "loss" "suffices" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
]
(* todo: don't use DELETENT for this *)
@@ -1285,12 +1289,12 @@ command: [
| WITH "Declare" "Scope" scope_name
(* odd that these are in command while other notation-related ones are in syntax *)
-| REPLACE "Numeral" "Notation" reference reference reference ":" ident numeral_modifier
-| WITH "Numeral" "Notation" reference reference reference ":" scope_name numeral_modifier
-| REPLACE "Number" "Notation" reference reference reference ":" ident numeral_modifier
-| WITH "Number" "Notation" reference reference reference ":" scope_name numeral_modifier
-| REPLACE "String" "Notation" reference reference reference ":" ident
-| WITH "String" "Notation" reference reference reference ":" scope_name
+| REPLACE "Number" "Notation" reference reference reference OPT number_options ":" ident
+| WITH "Number" "Notation" reference reference reference OPT number_options ":" scope_name
+| REPLACE "Numeral" "Notation" reference reference reference ":" ident deprecated_number_modifier
+| WITH "Numeral" "Notation" reference reference reference ":" scope_name deprecated_number_modifier
+| REPLACE "String" "Notation" reference reference reference OPT string_option ":" ident
+| WITH "String" "Notation" reference reference reference OPT string_option ":" scope_name
| DELETE "Ltac2" ltac2_entry (* was split up *)
| DELETE "Add" "Zify" "InjTyp" constr (* micromega plugin *)
@@ -1319,10 +1323,6 @@ command: [
| WITH "Goal" type
]
-option_setting: [
-| OPTINREF
-]
-
syntax: [
| REPLACE "Open" "Scope" IDENT
| WITH "Open" "Scope" scope
@@ -1358,10 +1358,6 @@ explicit_subentry: [
| DELETE "constr" (* covered by another prod *)
]
-numeral_modifier: [
-| OPTINREF
-]
-
binder_tactic: [
| REPLACE "let" [ "rec" | ] LIST1 let_clause SEP "with" "in" ltac_expr5
| WITH "let" OPT "rec" let_clause LIST0 ( "with" let_clause ) "in" ltac_expr5
@@ -1439,7 +1435,6 @@ cofix_definition: [
type_cstr: [
| REPLACE ":" lconstr
| WITH ":" type
-| OPTINREF
]
inductive_definition: [
@@ -1464,10 +1459,6 @@ record_binder: [
| DELETE name
]
-at_level_opt: [
-| OPTINREF
-]
-
query_command: [
| REPLACE "Eval" red_expr "in" lconstr "."
| WITH "Eval" red_expr "in" lconstr
@@ -1502,10 +1493,6 @@ vernac_toplevel: [
| DELETE vernac_control
]
-in_or_out_modules: [
-| OPTINREF
-]
-
vernac_control: [
(* replacing vernac_control with command is cheating a little;
they can't refer to the vernac_toplevel commands.
@@ -1521,90 +1508,8 @@ vernac_control: [
| DELETE decorated_vernac
]
-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: [
@@ -1651,43 +1556,18 @@ record_declaration: [
fields_def: [ | DELETENT ]
-hint_info: [
-| OPTINREF
-]
-
-debug: [
-| OPTINREF
-]
-
-eauto_search_strategy: [
-| OPTINREF
-]
-
-
constr_body: [
| DELETE ":=" lconstr
| REPLACE ":" lconstr ":=" lconstr
| WITH OPT ( ":" type ) ":=" 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
@@ -1706,22 +1586,9 @@ ltac2_in_clause: [
| DELETE LIST0 ltac2_hypident_occ SEP "," (* Ltac2 plugin *)
]
-concl_occ: [
-| OPTINREF
-]
-
-opt_coercion: [
-| OPTINREF
-]
-
-opt_constructors_or_fields: [
-| OPTINREF
-]
-
decl_notations: [
| REPLACE "where" LIST1 decl_notation SEP decl_sep
| WITH "where" decl_notation LIST0 (decl_sep decl_notation )
-| OPTINREF
]
module_expr: [
@@ -1782,15 +1649,6 @@ decl_notation: [
| WITH ne_lstring ":=" constr syntax_modifiers OPT [ ":" scope_name ]
]
-syntax_modifiers: [
-| OPTINREF
-]
-
-
-only_parsing: [
-| OPTINREF
-]
-
ltac_production_item: [
| REPLACE ident "(" ident OPT ltac_production_sep ")"
| WITH ident OPT ( "(" ident OPT ltac_production_sep ")" )
@@ -1912,6 +1770,7 @@ ltac_defined_tactics: [
| "lra"
| "nia"
| "nra"
+| "over" TAG SSR
| "split_Rabs"
| "split_Rmult"
| "tauto"
@@ -1923,10 +1782,12 @@ ltac_defined_tactics: [
tactic_notation_tactics: [
| "assert_fails" ltac_expr3
| "assert_succeeds" ltac_expr3
+| "dintuition" OPT ltac_expr5
+| "dtauto"
| "field" OPT ( "[" LIST1 constr "]" )
| "field_simplify" OPT ( "[" LIST1 constr "]" ) LIST1 constr OPT ( "in" ident )
| "field_simplify_eq" OPT ( "[" LIST1 constr "]" ) OPT ( "in" ident )
-| "intuition" OPT ltac_expr5
+| "intuition" OPT ltac_expr5 (* todo: Not too keen on things like "with_power_flags" in tauto.ml, not easy to follow *)
| "nsatz" OPT ( "with" "radicalmax" ":=" constr "strategy" ":=" constr "parameters" ":=" constr "variables" ":=" constr )
| "psatz" constr OPT int_or_var
| "ring" OPT ( "[" LIST1 constr "]" )
@@ -2028,10 +1889,6 @@ DELETE: [
| test_ltac1_env
]
-mut_flag: [
-| OPTINREF
-]
-
rec_flag: [
| OPTINREF
]
@@ -2046,18 +1903,6 @@ SPLICE: [
| ltac2_orient
]
-tac2typ_prm: [
-| OPTINREF
-]
-
-tac2type_body: [
-| OPTINREF
-]
-
-atomic_tac2pat: [
-| OPTINREF
-]
-
ltac2_expr0: [
(*
| DELETE "(" ")" (* covered by "()" prodn *)
@@ -2085,7 +1930,6 @@ tac2rec_fieldexprs: [
| DELETE tac2rec_fieldexpr ";"
| DELETE tac2rec_fieldexpr
| LIST1 tac2rec_fieldexpr OPT ";"
-| OPTINREF
]
tac2rec_fields: [
@@ -2093,7 +1937,6 @@ tac2rec_fields: [
| DELETE tac2rec_field ";"
| DELETE tac2rec_field
| LIST1 tac2rec_field SEP ";" OPT ";" TAG Ltac2
-| OPTINREF
]
(* todo: weird productions, ints only after an initial "-"??:
@@ -2107,46 +1950,6 @@ ltac2_occs_nums: [
| WITH OPT "-" LIST1 nat_or_anti TAG Ltac2
]
-syn_level: [
-| OPTINREF
-]
-
-ltac2_delta_flag: [
-| OPTINREF
-]
-
-ltac2_occs: [
-| OPTINREF
-]
-
-ltac2_concl_occ: [
-| OPTINREF
-]
-
-ltac2_with_bindings: [
-| OPTINREF
-]
-
-ltac2_as_or_and_ipat: [
-| OPTINREF
-]
-
-ltac2_eqn_ipat: [
-| OPTINREF
-]
-
-ltac2_as_name: [
-| OPTINREF
-]
-
-ltac2_as_ipat: [
-| OPTINREF
-]
-
-ltac2_by_tactic: [
-| OPTINREF
-]
-
ltac2_entry: [
| REPLACE tac2def_typ (* Ltac2 plugin *)
| WITH "Ltac2" tac2def_typ
@@ -2181,14 +1984,9 @@ SPLICE: [
| tac2def_ext
| tac2def_syn
| tac2def_mut
-| mut_flag
| rec_flag
| locident
-| syn_level
-| tac2rec_fieldexprs
-| tac2type_body
| tac2alg_constructors
-| tac2rec_fields
| ltac2_binder
| branch
| anti
@@ -2197,7 +1995,8 @@ SPLICE: [
ltac2_expr5: [
| REPLACE "let" OPT "rec" LIST1 ltac2_let_clause SEP "with" "in" ltac2_expr6 (* Ltac2 plugin *)
| WITH "let" OPT "rec" ltac2_let_clause LIST0 ( "with" ltac2_let_clause ) "in" ltac2_expr6 TAG Ltac2
-| MOVETO simple_tactic "match" ltac2_expr5 "with" OPT ltac2_branches "end" (* Ltac2 plugin *)
+| MOVETO simple_tactic "match" ltac2_expr5 "with" ltac2_branches "end" (* Ltac2 plugin *)
+| MOVETO simple_tactic "if" ltac2_expr5 "then" ltac2_expr5 "else" ltac2_expr5 (* Ltac2 plugin *)
| DELETE simple_tactic
]
@@ -2236,8 +2035,8 @@ q_clause: [
]
ltac2_induction_clause: [
-| REPLACE ltac2_destruction_arg OPT ltac2_as_or_and_ipat OPT ltac2_eqn_ipat OPT clause (* Ltac2 plugin *)
-| WITH ltac2_destruction_arg OPT ltac2_as_or_and_ipat OPT ltac2_eqn_ipat OPT ltac2_clause TAG Ltac2
+| REPLACE ltac2_destruction_arg ltac2_as_or_and_ipat ltac2_eqn_ipat OPT clause (* Ltac2 plugin *)
+| WITH ltac2_destruction_arg ltac2_as_or_and_ipat ltac2_eqn_ipat OPT ltac2_clause TAG Ltac2
]
starredidentref: [
@@ -2274,6 +2073,322 @@ ltac2_expr: [
| DELETE _ltac2_expr
]
+ssrfwdview: [
+| REPLACE "/" ast_closure_term ssrfwdview (* SSR plugin *)
+| WITH LIST1 ( "/" ast_closure_term ) TAG SSR
+| DELETE "/" ast_closure_term (* SSR plugin *)
+]
+
+ssrfwd: [
+| REPLACE ":" ast_closure_lterm ":=" ast_closure_lterm (* SSR plugin *)
+| WITH OPT ( ":" ast_closure_lterm ) ":=" ast_closure_lterm TAG SSR
+| DELETE ":=" ast_closure_lterm (* SSR plugin *)
+]
+
+ssrsetfwd: [
+| REPLACE ":" ast_closure_lterm ":=" "{" ssrocc "}" cpattern (* SSR plugin *)
+| WITH OPT ( ":" ast_closure_lterm ) ":=" [ "{" ssrocc "}" cpattern | lcpattern ] TAG SSR
+| DELETE ":" ast_closure_lterm ":=" lcpattern (* SSR plugin *)
+| DELETE ":=" "{" ssrocc "}" cpattern (* SSR plugin *)
+| DELETE ":=" lcpattern (* SSR plugin *)
+]
+
+
+(* per @gares *)
+ssrdgens: [
+| REPLACE ":" ssrgen ssrdgens_tl (* SSR plugin *)
+| WITH ":" ssrgen OPT ( "/" ssrgen ) TAG SSR
+]
+
+ssrdgens_tl: [ | DELETENT ]
+
+ssrgen: [
+| REPLACE ssrdocc cpattern (* SSR plugin *)
+| WITH cpattern LIST0 [ LIST1 ident | cpattern ] TAG SSR
+| DELETE cpattern (* SSR plugin *)
+]
+
+OPTINREF: [ ]
+
+ssrortacs: [
+| EDIT ssrtacarg "|" ADD_OPT ssrortacs (* ssr plugin *)
+| EDIT "|" ADD_OPT ssrortacs (* ssr plugin *)
+| EDIT ADD_OPT ssrtacarg "|" OPT ssrortacs
+]
+
+ssrocc: [
+| REPLACE natural LIST0 natural (* SSR plugin *)
+| WITH [ natural | "+" | "-" ] LIST0 natural TAG SSR
+| DELETE "-" LIST0 natural (* SSR plugin *)
+| DELETE "+" LIST0 natural (* SSR plugin *)
+]
+
+ssripat: [
+| DELETE ssrdocc "->" (* SSR plugin *)
+| DELETE ssrdocc "<-" (* SSR plugin *)
+| REPLACE ssrdocc (* SSR plugin *)
+| WITH ssrdocc OPT [ "->" | "<-" ] TAG SSR
+| DELETE "->" (* SSR plugin *)
+| DELETE "<-" (* SSR plugin *)
+| DELETE "-/" "=" (* SSR plugin *)
+| DELETE "-/" "/" (* SSR plugin *)
+| DELETE "-/" integer "/" (* SSR plugin *)
+| DELETE "-/" integer "/=" (* SSR plugin *)
+| REPLACE "-/" integer "/" integer "=" (* SSR plugin *)
+| WITH "-/" integer [ "/=" | "/" | "/" integer "=" ] TAG SSR
+| DELETE "-/" "/=" (* SSR plugin *)
+| DELETE "-//" "=" (* SSR plugin *)
+| DELETE "[" ":" LIST0 ident "]" (* SSR plugin *)
+]
+
+ssrsimpl_ne: [
+| DELETE "/" natural "/" "=" (* SSR plugin *)
+(* parsed but not supported per @gares *)
+| DELETE "/" natural "/" (* SSR plugin *)
+| DELETE "/" natural "=" (* SSR plugin *)
+| DELETE "//" natural "=" (* SSR plugin *)
+]
+
+hat: [
+| DELETE "^" "~" ident (* SSR plugin *)
+| DELETE "^" "~" natural (* SSR plugin *)
+]
+
+ssriorpat: [
+| ssripats OPT ( [ "|" | "|-" ] ssriorpat ) TAG SSR
+| DELETE OPT ssripats "|" ssriorpat (* SSR plugin *)
+| DELETE OPT ssripats "|-" ">" ssriorpat (* SSR plugin *)
+| DELETE OPT ssripats "|-" ssriorpat (* SSR plugin *)
+(* "|->" | "||" | "|||" | "||||" are parsing hacks *)
+| DELETE OPT ssripats "|->" ssriorpat (* SSR plugin *)
+| DELETE OPT ssripats "||" ssriorpat (* SSR plugin *)
+| DELETE OPT ssripats "|||" ssriorpat (* SSR plugin *)
+| DELETE OPT ssripats "||||" ssriorpat (* SSR plugin *)
+| DELETE OPT ssripats (* SSR plugin *)
+]
+
+ssrbinder: [
+| REPLACE "(" ssrbvar LIST1 ssrbvar ":" lconstr ")" (* SSR plugin *)
+| WITH "(" LIST1 ssrbvar ":" lconstr ")" TAG SSR
+| REPLACE "(" ssrbvar ":" lconstr ":=" lconstr ")" (* SSR plugin *)
+| WITH "(" ssrbvar OPT ( ":" lconstr ) OPT ( ":=" lconstr ) ")" TAG SSR
+| DELETE "(" ssrbvar ")" (* SSR plugin *)
+| DELETE "(" ssrbvar ":" lconstr ")" (* SSR plugin *)
+| DELETE "(" ssrbvar ":=" lconstr ")" (* SSR plugin *)
+]
+
+ssrhavefwd: [
+| REPLACE ":" ast_closure_lterm ":=" ast_closure_lterm (* SSR plugin *)
+| WITH ":" ast_closure_lterm ":=" OPT ast_closure_lterm TAG SSR
+| DELETE ":" ast_closure_lterm ":=" (* SSR plugin *)
+| DELETE ":=" ast_closure_lterm (* SSR plugin *)
+]
+
+ssrmult_ne: [
+| EDIT ADD_OPT natural ssrmmod TAG SSR
+]
+
+rpattern: [
+| REPLACE lconstr "in" lconstr "in" lconstr (* SSR plugin *)
+| WITH OPT ( OPT ( OPT ( OPT lconstr "in" ) lconstr ) "in" ) lconstr TAG SSR
+| DELETE lconstr (* SSR plugin *)
+| DELETE "in" lconstr (* SSR plugin *)
+| DELETE lconstr "in" lconstr (* SSR plugin *)
+| DELETE "in" lconstr "in" lconstr (* SSR plugin *)
+]
+
+ssrrule_ne: [
+| DELETE ssrsimpl_ne (* SSR plugin *)
+| REPLACE [ "/" ssrterm | ssrterm | ssrsimpl_ne ] (* SSR plugin *)
+| WITH [ OPT "/" ssrterm | ssrsimpl_ne ] TAG SSR
+]
+
+ssrunlockarg: [
+| REPLACE "{" ssrocc "}" ssrterm (* SSR plugin *)
+| WITH OPT ( "{" ssrocc "}" ) ssrterm TAG SSR
+| DELETE ssrterm (* SSR plugin *)
+]
+
+ssrclauses: [
+| REPLACE "in" ssrclausehyps "|-" "*" (* SSR plugin *)
+| WITH "in" ssrclausehyps OPT "|-" OPT "*" TAG SSR
+| DELETE "in" ssrclausehyps "|-" (* SSR plugin *)
+| DELETE "in" ssrclausehyps "*" (* SSR plugin *)
+| DELETE "in" ssrclausehyps (* SSR plugin *)
+| REPLACE "in" "|-" "*" (* SSR plugin *)
+| WITH "in" [ "*" | "*" "|-" | "|-" "*" ] TAG SSR
+| DELETE "in" "*" (* SSR plugin *)
+| DELETE "in" "*" "|-" (* SSR plugin *)
+]
+
+ssrclausehyps: [
+| REPLACE ssrwgen "," ssrclausehyps (* SSR plugin *)
+| WITH ssrwgen LIST0 ( OPT "," ssrwgen ) TAG SSR
+| DELETE ssrwgen ssrclausehyps (* SSR plugin *)
+| DELETE ssrwgen (* SSR plugin *)
+]
+
+ssrwgen: [
+| DELETE ssrhoi_hyp (* SSR plugin *)
+| REPLACE "@" ssrhoi_hyp (* SSR plugin *)
+| WITH OPT "@" ssrhoi_hyp TAG SSR
+| REPLACE "(" ssrhoi_id ":=" lcpattern ")" (* SSR plugin *)
+| WITH "(" ssrhoi_id OPT ( ":=" lcpattern ) ")" TAG SSR
+| DELETE "(" ssrhoi_id ")" (* SSR plugin *)
+| DELETE "(" "@" ssrhoi_id ":=" lcpattern ")" (* SSR plugin *)
+]
+
+ssrcongrarg: [
+| REPLACE natural constr ssrdgens (* SSR plugin *)
+| WITH OPT natural constr OPT ssrdgens TAG SSR
+| DELETE natural constr (* SSR plugin *)
+| DELETE constr ssrdgens (* SSR plugin *)
+| DELETE constr (* SSR plugin *)
+]
+
+ssrviewpos: [
+| DELETE "for" "apply" "/" "/" (* SSR plugin *)
+]
+
+ssrhintref: [
+| REPLACE constr "|" natural (* SSR plugin *)
+| WITH constr OPT ( "|" natural ) TAG SSR
+| DELETE constr (* SSR plugin *)
+]
+
+ssr_search_arg: [
+| REPLACE "-" ssr_search_item OPT ssr_search_arg (* SSR plugin *)
+| WITH LIST1 ( "-" ssr_search_item ) TAG SSR
+| DELETE ssr_search_item OPT ssr_search_arg (* SSR plugin *)
+]
+
+ssr_search_item: [
+| DELETE string (* SSR plugin *)
+| REPLACE string "%" preident (* SSR plugin *)
+| WITH string OPT ( "%" preident ) TAG SSR
+]
+
+modloc: [
+| REPLACE "-" global (* SSR plugin *)
+| WITH OPT "-" global TAG SSR
+| DELETE global
+]
+
+ssrmmod: [
+| DELETE LEFTQMARK (* SSR plugin *) (* duplicate *)
+]
+
+clear_switch: [
+| "{" LIST0 ident "}"
+]
+
+ssrrwocc: [
+| REPLACE "{" LIST0 ssrhyp "}" (* SSR plugin *)
+| WITH clear_switch
+]
+
+ssrrwarg: [
+| EDIT "{" ADD_OPT ssrocc "}" OPT ssrpattern_squarep ssrrule_ne TAG SSR
+| REPLACE "{" LIST1 ssrhyp "}" ssrpattern_ne_squarep ssrrule_ne (* SSR plugin *)
+| WITH OPT ( OPT ( "{" LIST1 ssrhyp "}" ) ssrpattern_ne_squarep ) ssrrule_ne TAG SSR
+| DELETE ssrpattern_ne_squarep ssrrule_ne (* SSR plugin *)
+| DELETE ssrrule_ne (* SSR plugin *)
+]
+
+ssrpattern_squarep: [ (* fix inconsistency *)
+| REPLACE "[" rpattern "]" (* SSR plugin *)
+| WITH ssrpattern_ne_squarep TAG SSR
+]
+
+ssripats_ne: [
+| REPLACE ssripat OPT ssripats (* SSR plugin *)
+| WITH LIST1 ssripat TAG SSR
+]
+
+ssripats: [ (* fix inconsistency *)
+| REPLACE ssripat OPT ssripats (* SSR plugin *)
+| WITH ssripats_ne TAG SSR
+]
+
+lcpattern: [
+(* per @gares *)
+| DELETE "Qed" lconstr
+]
+
+ssrapplyarg: [
+| EDIT ADD_OPT ssrbwdview ":" ssragen OPT ssragens OPT ssrintros TAG SSR
+]
+
+constr_with_bindings_arg: [
+| EDIT ADD_OPT ">" constr_with_bindings TAG SSR
+]
+
+destruction_arg: [
+| DELETE constr_with_bindings
+]
+
+ssrhintarg: [
+| EDIT "[" ADD_OPT ssrortacs "]" TAG SSR
+]
+
+
+ssrhint3arg: [
+| EDIT "[" ADD_OPT ssrortacs "]" TAG SSR
+]
+
+
+ssr_first: [
+| DELETE ssr_first ssrintros_ne (* SSR plugin *)
+| REPLACE "[" LIST0 ltac_expr5 SEP "|" "]" (* SSR plugin *)
+| WITH "[" LIST0 ltac_expr5 SEP "|" "]" LIST0 ssrintros_ne TAG SSR
+]
+
+ssr_first_else: [
+| EDIT ssr_first ADD_OPT ssrorelse TAG SSR
+]
+
+ssrseqarg: [
+| EDIT ADD_OPT ssrseqidx ssrswap TAG SSR
+]
+
+ssr_dpat: [
+| REPLACE ssr_mpat "in" pattern200 ssr_rtype (* SSR plugin *)
+| WITH ssr_mpat OPT ( OPT ( "in" pattern200 ) ssr_rtype ) TAG SSR
+| DELETE ssr_mpat ssr_rtype (* SSR plugin *)
+| DELETE ssr_mpat (* SSR plugin *)
+]
+
+ssr_one_term_pattern: [
+| DELETE "Qed" constr
+]
+
+ssrarg: [
+| EDIT ADD_OPT ssrfwdview OPT ssreqid ssrdgens OPT ssrintros (* SSR plugin *)
+]
+
+ssragen: [
+| REPLACE "{" LIST1 ssrhyp "}" ssrterm (* SSR plugin *)
+| WITH OPT ( "{" LIST1 ssrhyp "}" ) ssrterm TAG SSR
+| DELETE ssrterm (* SSR plugin *)
+]
+
+ssrbinder: [
+| REPLACE [ "of" | "&" ] term99 (* SSR plugin *)
+| WITH "of" term99 TAG SSR
+| "&" term99 TAG SSR
+]
+
+firstorder_rhs: [
+| DELETE OPT firstorder_using
+| DELETE "with" LIST1 preident
+| REPLACE OPT firstorder_using "with" LIST1 preident
+| WITH OPT firstorder_using OPT ( "with" LIST1 preident )
+]
+
+attribute: [
+| DELETE "using" OPT attr_value
+]
+
SPLICE: [
| clause
| noedit_mode
@@ -2309,18 +2424,16 @@ SPLICE: [
| bar_cbrace
| lconstr
-(*
+(* SSR *)
| ast_closure_term
| ast_closure_lterm
| ident_no_do
| ssrterm
| ssrtacarg
| ssrtac3arg
-| ssrtclarg
| ssrhyp
| ssrhoi_hyp
| ssrhoi_id
-| ssrindex
| ssrhpats
| ssrhpats_nobs
| ssrfwdid
@@ -2335,17 +2448,39 @@ SPLICE: [
| ssrcofixfwd
| ssrfixfwd
| ssrhavefwdwbinders
-| ssripats_ne
| ssrparentacarg
| ssrposefwd
-*)
-
+| ssrstruct
+| ssrrpat
+| ssrhint
+| ssrpattern_squarep
+| ssrhintref
+| ssr_search_item
+| ssr_modlocs
+| modloc
+| ssrexactarg
+| ssrclear
+| ssrmult
+| ssripats
+| ssrintros
+| ssrrule
+| ssrpattern_squarep
+| ssrcongrarg
+| ssrdotac
+| ssrunlockarg
+| ssr_search_arg
+| ssrortacarg
+| ssrsetfwd
+| ssr_idcomma
+| ssr_dthen
+| ssr_else
+| ssr_rtype
+| ssreqid
| preident
| lpar_id_coloneq
| binders
| casted_constr
| check_module_types
-| constr_pattern
| decl_sep
| function_fix_definition (* loses funind annotation *)
| glob
@@ -2464,6 +2599,16 @@ SPLICE: [
| constr_with_bindings
| simple_binding
| ssexpr35 (* strange in mlg, ssexpr50 is after this *)
+| number_string_mapping
+| number_options
+| string_option
+| tac2type_body
+| tac2rec_fields
+| mut_flag
+| tac2rec_fieldexprs
+| syn_level
+| firstorder_rhs
+| firstorder_using
] (* end SPLICE *)
RENAME: [
@@ -2493,6 +2638,23 @@ RENAME: [
| ltac2_type5 ltac2_type
| ltac2_expr6 ltac2_expr
| starredidentref starred_ident_ref
+| ssrocc ssr_occurrences
+| ssrsimpl_ne s_item
+| ssrclear_ne ssrclear
+| ssrmult_ne mult
+| ssripats_ne ssripats
+| ssrrule_ne r_item
+| ssrintros_ne ssrintros
+| ssrpattern_ne_squarep ssrpattern_squarep
+| ssrrwarg rewrite_item
+| ssrrwocc occ_or_clear
+| rpattern rewrite_pattern
+| ssripat i_item
+| ssrwgen gen_item
+| ssrfwd ssrdefbody
+| ssrclauses ssr_in
+| ssrcpat ssrblockpat
+| constr_pattern one_pattern
]
simple_tactic: [
@@ -2500,11 +2662,6 @@ simple_tactic: [
| qualid LIST1 tactic_arg
]
-(* todo: doesn't work if up above... maybe because 'clause' doesn't exist? *)
-clause_dft_concl: [
-| OPTINREF
-]
-
SPLICE: [
| gallina
| gallina_ext
diff --git a/doc/tools/docgram/doc_grammar.ml b/doc/tools/docgram/doc_grammar.ml
index b7f1e18d2b..92a745c863 100644
--- a/doc/tools/docgram/doc_grammar.ml
+++ b/doc/tools/docgram/doc_grammar.ml
@@ -12,12 +12,14 @@ open Coqpp_parser
open Coqpp_ast
let exit_code = ref 0
+let error_count = ref 0
let show_warn = ref true
let fprintf = Printf.fprintf
let error s =
exit_code := 1;
+ incr error_count;
Printf.eprintf "Error: ";
Printf.eprintf s
@@ -309,6 +311,11 @@ let rec output_prodn = function
| "{|" -> "%{%|"
| "`{" -> "`%{"
| "@{" -> "@%{"
+ | "|-" -> "%|-"
+ | "|->" -> "%|->"
+ | "||" -> "%||"
+ | "|||" -> "%|||"
+ | "||||" -> "%||||"
| "{"
| "}"
| "|" -> "%" ^ s
@@ -354,10 +361,9 @@ and prod_to_prodn prod = String.concat " " (prod_to_prodn_r prod)
let get_tag file prod =
List.fold_left (fun rv sym ->
match sym with
- (* todo: temporarily limited to Ltac2 tags in prodn when not in ltac2.rst *)
- | Sedit2 ("TAG", s2)
- when (s2 = "Ltac2" || s2 = "not Ltac2") &&
- file <> "doc/sphinx/proof-engine/ltac2.rst" -> " " ^ s2
+ (* todo: only Ltac2 and SSR for now, outside of their main chapters *)
+ | Sedit2 ("TAG", "Ltac2") when file <> "doc/sphinx/proof-engine/ltac2.rst" -> " Ltac2"
+ | Sedit2 ("TAG", "SSR") when file <> "doc/sphinx/proof-engine/ssreflect-proof-language.rst" -> " SSR"
| _ -> rv
) "" prod
@@ -538,12 +544,11 @@ let autoloaded_mlgs = [ (* in the order they are loaded by Coq *)
"plugins/ltac/g_eqdecide.mlg";
"plugins/ltac/g_tactic.mlg";
"plugins/ltac/g_ltac.mlg";
- "plugins/syntax/g_string.mlg";
"plugins/btauto/g_btauto.mlg";
"plugins/rtauto/g_rtauto.mlg";
"plugins/cc/g_congruence.mlg";
"plugins/firstorder/g_ground.mlg";
- "plugins/syntax/g_numeral.mlg";
+ "plugins/syntax/g_number_string.mlg";
]
@@ -555,6 +560,10 @@ let level_regex = Str.regexp "[a-zA-Z0-9_]*$"
let get_plugin_name file =
if file = "user-contrib/Ltac2/g_ltac2.mlg" then
"Ltac2"
+ (* todo: would be better if g_search.mlg has an "ssr" prefix *)
+ else if List.mem file ["plugins/ssr/ssrparser.mlg"; "plugins/ssr/ssrvernac.mlg";
+ "plugins/ssrmatching/g_ssrmatching.mlg"; "plugins/ssrsearch/g_search.mlg"] then
+ "SSR"
else if Str.string_match plugin_regex file 0 then
Str.matched_group 1 file
else
@@ -564,12 +573,12 @@ let read_mlg g is_edit ast file level_renames symdef_map =
let res = ref [] in
let locals = ref StringSet.empty in
let dup_renames = ref StringMap.empty in
- let add_prods nt prods =
+ let add_prods nt prods gramext_globals =
if not is_edit then
- if NTMap.mem nt !g.map && nt <> "command" && nt <> "simple_tactic" then begin
+ if NTMap.mem nt !g.map && not (List.mem nt gramext_globals) && nt <> "command" && nt <> "simple_tactic" then begin
let new_name = String.uppercase_ascii (Filename.remove_extension (Filename.basename file)) ^ "_" ^ nt in
dup_renames := StringMap.add nt new_name !dup_renames;
- Printf.printf "** dup sym %s -> %s in %s\n" nt new_name file
+ if false then Printf.printf "** dup local sym %s -> %s in %s\n" nt new_name file
end;
add_symdef nt file symdef_map;
let plugin = get_plugin_name file in
@@ -590,11 +599,12 @@ let read_mlg g is_edit ast file level_renames symdef_map =
| Some s -> s
| None -> ""
in
+ let gramext_globals = ref grammar_ext.gramext_globals in
List.iter (fun ent ->
let len = List.length ent.gentry_rules in
List.iteri (fun i rule ->
let nt = ent.gentry_name in
- if not (List.mem nt grammar_ext.gramext_globals) then
+ if not (List.mem nt !gramext_globals) then
locals := StringSet.add nt !locals;
let level = (get_label rule.grule_label) in
let level = if level <> "" then level else
@@ -625,8 +635,11 @@ let read_mlg g is_edit ast file level_renames symdef_map =
if cur_level <> nt && i+1 < len then
edited @ [[Snterm next_level]]
else
- edited in
- add_prods cur_level prods_to_add)
+ edited
+ in
+ if cur_level <> nt && List.mem nt !gramext_globals then
+ gramext_globals := cur_level :: !gramext_globals;
+ add_prods cur_level prods_to_add !gramext_globals)
ent.gentry_rules
) grammar_ext.gramext_entries
@@ -636,16 +649,16 @@ let read_mlg g is_edit ast file level_renames symdef_map =
| Some c -> String.trim c.code
in
add_prods node
- (List.map (fun r -> cvt_ext r.vernac_toks) vernac_ext.vernacext_rules)
+ (List.map (fun r -> cvt_ext r.vernac_toks) vernac_ext.vernacext_rules) []
| VernacArgumentExt vernac_argument_ext ->
add_prods vernac_argument_ext.vernacargext_name
- (List.map (fun r -> cvt_ext r.tac_toks) vernac_argument_ext.vernacargext_rules)
+ (List.map (fun r -> cvt_ext r.tac_toks) vernac_argument_ext.vernacargext_rules) []
| TacticExt tactic_ext ->
add_prods "simple_tactic"
- (List.map (fun r -> cvt_ext r.tac_toks) tactic_ext.tacext_rules)
+ (List.map (fun r -> cvt_ext r.tac_toks) tactic_ext.tacext_rules) []
| ArgumentExt argument_ext ->
add_prods argument_ext.argext_name
- (List.map (fun r -> cvt_ext r.tac_toks) argument_ext.argext_rules)
+ (List.map (fun r -> cvt_ext r.tac_toks) argument_ext.argext_rules) []
| _ -> ()
in
@@ -1191,6 +1204,15 @@ let edit_all_prods g op eprods =
| "DELETE" -> do_it op eprods 1; true
| "SPLICE" -> do_it op eprods 1; true
| "MERGE" -> do_it op eprods 2; true
+ | "OPTINREF" ->
+ List.iter (fun nt ->
+ let prods = NTMap.find nt !g.map in
+ if has_match [] prods then begin
+ let prods' = remove_prod [] prods nt in
+ g_update_prods g nt prods';
+ global_repl g [(Snterm nt)] [(Sopt (Snterm nt))]
+ end)
+ !g.order; true
| "EXPAND" ->
if List.length eprods > 1 || List.length (List.hd eprods) <> 0 then
error "'EXPAND:' expects a single empty production\n";
@@ -1897,7 +1919,10 @@ let process_rst g file args seen tac_prods cmd_prods =
let cmd_exclude_files = [
"doc/sphinx/proof-engine/ssreflect-proof-language.rst";
- "doc/sphinx/proof-engine/tactics.rst"
+ "doc/sphinx/proofs/automatic-tactics/auto.rst";
+ "doc/sphinx/proofs/writing-proofs/rewriting.rst";
+ "doc/sphinx/proofs/writing-proofs/proof-mode.rst";
+ "doc/sphinx/proof-engine/tactics.rst";
]
in
@@ -2008,10 +2033,11 @@ let report_omitted_prods g seen label split =
(if first = "" then nt else first), nt, n + 1, total + 1)
("", "", 0, 0) !g.order in
maybe_warn first last n;
-(* List.iter (fun nt ->
- if not (NTMap.mem nt seen || (List.mem nt included)) then
- warn "%s %s not included in .rst files\n" "Nonterminal" nt)
- !g.order;*)
+ Printf.printf "\n\n";
+ NTMap.iter (fun nt _ ->
+ if not (NTMap.mem nt seen || (List.mem nt included)) then
+ warn "%s %s not included in .rst files\n" "Nonterminal" nt)
+ !g.map;
if total <> 0 then
Printf.eprintf "TOTAL %ss not included = %d\n" label total
@@ -2074,7 +2100,7 @@ let process_grammar args =
print_in_order out g `MLG !g.order StringSet.empty;
close_out out;
finish_with_file (dir "orderedGrammar") args;
- check_singletons g;
+(* check_singletons g*)
(* print_dominated g*)
let seen = ref { nts=NTMap.empty; tacs=NTMap.empty; tacvs=NTMap.empty; cmds=NTMap.empty; cmdvs=NTMap.empty } in
@@ -2169,5 +2195,7 @@ let () =
if !exit_code = 0 then begin
process_grammar args
end;
+ if !error_count > 0 then
+ Printf.eprintf "%d error(s)\n" !error_count;
exit !exit_code
(*with _ -> Printexc.print_backtrace stdout; exit 1*)
diff --git a/doc/tools/docgram/dune b/doc/tools/docgram/dune
index 2a7b283f55..1c07d00d4f 100644
--- a/doc/tools/docgram/dune
+++ b/doc/tools/docgram/dune
@@ -12,7 +12,6 @@
(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)
@@ -23,8 +22,11 @@
(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/ring/*.mlg)
+ (glob_files %{project_root}/plugins/rtauto/*.mlg)
+ (glob_files %{project_root}/plugins/ssr/*.mlg)
+ (glob_files %{project_root}/plugins/ssrmatching/*.mlg)
+ (glob_files %{project_root}/plugins/ssrsearch/*.mlg)
(glob_files %{project_root}/plugins/syntax/*.mlg)
(glob_files %{project_root}/user-contrib/Ltac2/*.mlg)
; Sphinx files
diff --git a/doc/tools/docgram/fullGrammar b/doc/tools/docgram/fullGrammar
index c764cb6f37..a787d769fb 100644
--- a/doc/tools/docgram/fullGrammar
+++ b/doc/tools/docgram/fullGrammar
@@ -119,6 +119,7 @@ term0: [
| "`{" term200 "}"
| test_array_opening "[" "|" array_elems "|" lconstr type_cstr test_array_closing "|" "]" univ_annot
| "`(" term200 ")"
+| "ltac" ":" "(" Pltac.ltac_expr ")"
]
array_elems: [
@@ -152,6 +153,11 @@ binder_constr: [
| "if" term200 as_return_type "then" term200 "else" term200
| "fix" fix_decls
| "cofix" cofix_decls
+| "if" term200 "is" ssr_dthen ssr_else (* SSR plugin *)
+| "if" term200 "isn't" ssr_dthen ssr_else (* SSR plugin *)
+| "let" ":" ssr_mpat ":=" lconstr "in" lconstr (* SSR plugin *)
+| "let" ":" ssr_mpat ":=" lconstr ssr_rtype "in" lconstr (* SSR plugin *)
+| "let" ":" ssr_mpat "in" pattern200 ":=" lconstr ssr_rtype "in" lconstr (* SSR plugin *)
]
arg: [
@@ -308,6 +314,7 @@ open_binders: [
binders: [
| LIST0 binder
+| Pcoq.Constr.binders
]
binder: [
@@ -332,6 +339,7 @@ closed_binder: [
| "`{" LIST1 typeclass_constraint SEP "," "}"
| "`[" LIST1 typeclass_constraint SEP "," "]"
| "'" pattern0
+| [ "of" | "&" ] term99 (* SSR plugin *)
]
typeclass_constraint: [
@@ -632,20 +640,20 @@ command: [
| "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
| "Add" "Relation" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
| "Add" "Relation" constr constr "transitivity" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "reflexivity" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "symmetry" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
-| "Add" "Parametric" "Relation" G_REWRITE_binders ":" constr constr "transitivity" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "reflexivity" "proved" "by" constr "symmetry" "proved" "by" constr "transitivity" "proved" "by" constr "as" ident
+| "Add" "Parametric" "Relation" binders ":" constr constr "transitivity" "proved" "by" constr "as" ident
| "Add" "Setoid" constr constr constr "as" ident
-| "Add" "Parametric" "Setoid" G_REWRITE_binders ":" constr constr constr "as" ident
+| "Add" "Parametric" "Setoid" binders ":" constr constr constr "as" ident
| "Add" "Morphism" constr ":" ident
| "Declare" "Morphism" constr ":" ident
| "Add" "Morphism" constr "with" "signature" lconstr "as" ident
-| "Add" "Parametric" "Morphism" G_REWRITE_binders ":" constr "with" "signature" lconstr "as" ident
+| "Add" "Parametric" "Morphism" binders ":" constr "with" "signature" lconstr "as" ident
| "Print" "Rewrite" "HintDb" preident
| "Reset" "Ltac" "Profile"
| "Show" "Ltac" "Profile"
@@ -686,9 +694,13 @@ command: [
| "Print" "Rings" (* ring plugin *)
| "Add" "Field" ident ":" constr OPT field_mods (* ring plugin *)
| "Print" "Fields" (* ring plugin *)
-| "Number" "Notation" reference reference reference ":" ident numeral_modifier
-| "Numeral" "Notation" reference reference reference ":" ident numeral_modifier
-| "String" "Notation" reference reference reference ":" ident
+| "Prenex" "Implicits" LIST1 global (* SSR plugin *)
+| "Print" "Hint" "View" ssrviewpos (* SSR plugin *)
+| "Hint" "View" ssrviewposspc LIST1 ssrhintref (* SSR plugin *)
+| "Search" ssr_search_arg ssr_modlocs (* SSR plugin *)
+| "Number" "Notation" reference reference reference OPT number_options ":" ident
+| "Numeral" "Notation" reference reference reference ":" ident deprecated_number_modifier
+| "String" "Notation" reference reference reference OPT string_option ":" ident
| "Ltac2" ltac2_entry (* Ltac2 plugin *)
| "Ltac2" "Eval" ltac2_expr6 (* Ltac2 plugin *)
| "Print" "Ltac2" reference (* Ltac2 plugin *)
@@ -713,6 +725,7 @@ hint: [
| "Mode" global mode
| "Unfold" LIST1 global
| "Constructors" LIST1 global
+| "Extern" natural OPT Constr.constr_pattern "=>" Pltac.tactic
]
constr_body: [
@@ -746,6 +759,7 @@ attribute_list: [
attribute: [
| ident attr_value
+| "using" attr_value
]
attr_value: [
@@ -1021,6 +1035,7 @@ gallina_ext: [
| "Generalizable" [ "All" "Variables" | "No" "Variables" | [ "Variable" | "Variables" ] LIST1 identref ]
| "Export" "Set" setting_name option_setting
| "Export" "Unset" setting_name
+| "Import" "Prenex" "Implicits" (* SSR plugin *)
]
filtered_import: [
@@ -1743,6 +1758,51 @@ simple_tactic: [
| "ring_lookup" tactic0 "[" LIST0 constr "]" LIST1 constr (* ring plugin *)
| "field_lookup" tactic "[" LIST0 constr "]" LIST1 constr (* ring plugin *)
| "rtauto"
+| "by" ssrhintarg (* SSR plugin *)
+| "clear" natural (* SSR plugin *)
+| "move" ssrmovearg ssrrpat (* SSR plugin *)
+| "move" ssrmovearg ssrclauses (* SSR plugin *)
+| "move" ssrrpat (* SSR plugin *)
+| "move" (* SSR plugin *)
+| "case" ssrcasearg ssrclauses (* SSR plugin *)
+| "case" (* SSR plugin *)
+| "elim" ssrarg ssrclauses (* SSR plugin *)
+| "elim" (* SSR plugin *)
+| "apply" ssrapplyarg (* SSR plugin *)
+| "apply" (* SSR plugin *)
+| "exact" ssrexactarg (* SSR plugin *)
+| "exact" (* SSR plugin *)
+| "exact" "<:" lconstr (* SSR plugin *)
+| "congr" ssrcongrarg (* SSR plugin *)
+| "ssrinstancesofruleL2R" ssrterm (* SSR plugin *)
+| "ssrinstancesofruleR2L" ssrterm (* SSR plugin *)
+| "rewrite" ssrrwargs ssrclauses (* SSR plugin *)
+| "unlock" ssrunlockargs ssrclauses (* SSR plugin *)
+| "pose" ssrfixfwd (* SSR plugin *)
+| "pose" ssrcofixfwd (* SSR plugin *)
+| "pose" ssrfwdid ssrposefwd (* SSR plugin *)
+| "set" ssrfwdid ssrsetfwd ssrclauses (* SSR plugin *)
+| "abstract" ssrdgens (* SSR plugin *)
+| "have" ssrhavefwdwbinders (* SSR plugin *)
+| "have" "suff" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| "have" "suffices" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| "suff" "have" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| "suffices" "have" ssrhpats_nobs ssrhavefwd (* SSR plugin *)
+| "suff" ssrsufffwd (* SSR plugin *)
+| "suffices" ssrsufffwd (* SSR plugin *)
+| "wlog" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "wlog" "suff" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "wlog" "suffices" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "without" "loss" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "without" "loss" "suff" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "without" "loss" "suffices" ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "gen" "have" ssrclear ssr_idcomma ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "generally" "have" ssrclear ssr_idcomma ssrhpats_nobs ssrwlogfwd ssrhint (* SSR plugin *)
+| "under" ssrrwarg (* SSR plugin *)
+| "under" ssrrwarg ssrintros_ne (* SSR plugin *)
+| "under" ssrrwarg ssrintros_ne "do" ssrhint3arg (* SSR plugin *)
+| "under" ssrrwarg "do" ssrhint3arg (* SSR plugin *)
+| "ssrinstancesoftpat" G_SSRMATCHING_cpattern (* SSR plugin *)
]
mlname: [
@@ -1763,9 +1823,7 @@ language: [
]
firstorder_using: [
-| "using" reference
-| "using" reference "," LIST1 reference SEP ","
-| "using" reference reference LIST0 reference
+| "using" LIST1 reference SEP ","
|
]
@@ -1849,6 +1907,10 @@ by_arg_tac: [
in_clause: [
| in_clause'
+| "*" occs
+| "*" "|-" concl_occ
+| LIST0 hypident_occ SEP "," "|-" concl_occ
+| LIST0 hypident_occ SEP ","
]
test_lpar_id_colon: [
@@ -1950,6 +2012,9 @@ ltac_expr4: [
| ltac_expr3 ";" ltac_expr3
| ltac_expr3 ";" tactic_then_locality for_each_goal "]"
| ltac_expr3
+| ltac_expr5 ";" "first" ssr_first_else (* SSR plugin *)
+| ltac_expr5 ";" "first" ssrseqarg (* SSR plugin *)
+| ltac_expr5 ";" "last" ssrseqarg (* SSR plugin *)
]
ltac_expr3: [
@@ -1966,6 +2031,10 @@ ltac_expr3: [
| "abstract" ltac_expr2 "using" ident
| "only" selector ":" ltac_expr3
| ltac_expr2
+| "do" ssrmmod ssrdotac ssrclauses (* SSR plugin *)
+| "do" ssrortacarg ssrclauses (* SSR plugin *)
+| "do" int_or_var ssrmmod ssrdotac ssrclauses (* SSR plugin *)
+| "abstract" ssrdgens (* SSR plugin *)
]
ltac_expr2: [
@@ -1989,12 +2058,14 @@ ltac_expr1: [
| tactic_value
| reference LIST0 tactic_arg
| ltac_expr0
+| ltac_expr5 ssrintros_ne (* SSR plugin *)
]
ltac_expr0: [
| "(" ltac_expr5 ")"
| "[" ">" for_each_goal "]"
| tactic_atom
+| ssrparentacarg (* SSR plugin *)
]
failkw: [
@@ -2139,14 +2210,6 @@ tactic_mode: [
| "par" ":" OPT ltac_info tactic ltac_use_default
]
-G_LTAC_hint: [
-| "Extern" natural OPT Constr.constr_pattern "=>" Pltac.tactic
-]
-
-G_LTAC_term0: [
-| "ltac" ":" "(" Pltac.ltac_expr ")"
-]
-
ltac_selector: [
| toplevel_selector
]
@@ -2217,10 +2280,6 @@ rewstrategy: [
| "fold" constr
]
-G_REWRITE_binders: [
-| Pcoq.Constr.binders
-]
-
int_or_var: [
| integer
| identref
@@ -2393,32 +2452,27 @@ hypident: [
| id_or_meta
| "(" "type" "of" id_or_meta ")"
| "(" "value" "of" id_or_meta ")"
+| "(" "type" "of" Prim.identref ")" (* SSR plugin *)
+| "(" "value" "of" Prim.identref ")" (* SSR plugin *)
]
hypident_occ: [
| hypident occs
]
-G_TACTIC_in_clause: [
-| "*" occs
-| "*" "|-" concl_occ
-| LIST0 hypident_occ SEP "," "|-" concl_occ
-| LIST0 hypident_occ SEP ","
-]
-
clause_dft_concl: [
-| "in" G_TACTIC_in_clause
+| "in" in_clause
| occs
|
]
clause_dft_all: [
-| "in" G_TACTIC_in_clause
+| "in" in_clause
|
]
opt_clause: [
-| "in" G_TACTIC_in_clause
+| "in" in_clause
| "at" occs_nums
|
]
@@ -2549,12 +2603,630 @@ field_mods: [
| "(" LIST1 field_mod SEP "," ")" (* ring plugin *)
]
-numeral_modifier: [
+ssrtacarg: [
+| ltac_expr5 (* SSR plugin *)
+]
+
+ssrtac3arg: [
+| ltac_expr3 (* SSR plugin *)
+]
+
+ssrtclarg: [
+| ssrtacarg (* SSR plugin *)
+]
+
+ssrhyp: [
+| ident (* SSR plugin *)
+]
+
+ssrhoi_hyp: [
+| ident (* SSR plugin *)
+]
+
+ssrhoi_id: [
+| ident (* SSR plugin *)
+]
+
+ssrsimpl_ne: [
+| "//=" (* SSR plugin *)
+| "/=" (* SSR plugin *)
+| test_ssrslashnum11 "/" natural "/" natural "=" (* SSR plugin *)
+| test_ssrslashnum10 "/" natural "/" (* SSR plugin *)
+| test_ssrslashnum10 "/" natural "=" (* SSR plugin *)
+| test_ssrslashnum10 "/" natural "/=" (* SSR plugin *)
+| test_ssrslashnum10 "/" natural "/" "=" (* SSR plugin *)
+| test_ssrslashnum01 "//" natural "=" (* SSR plugin *)
+| test_ssrslashnum00 "//" (* SSR plugin *)
+]
+
+ssrclear_ne: [
+| "{" LIST1 ssrhyp "}" (* SSR plugin *)
+]
+
+ssrclear: [
+| ssrclear_ne (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrindex: [
+]
+
+ssrocc: [
+| natural LIST0 natural (* SSR plugin *)
+| "-" LIST0 natural (* SSR plugin *)
+| "+" LIST0 natural (* SSR plugin *)
+]
+
+ssrmmod: [
+| "!" (* SSR plugin *)
+| LEFTQMARK (* SSR plugin *)
+| "?" (* SSR plugin *)
+]
+
+ssrmult_ne: [
+| natural ssrmmod (* SSR plugin *)
+| ssrmmod (* SSR plugin *)
+]
+
+ssrmult: [
+| ssrmult_ne (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrdocc: [
+| "{" ssrocc "}" (* SSR plugin *)
+| "{" LIST0 ssrhyp "}" (* SSR plugin *)
+]
+
+ssrterm: [
+| ssrtermkind Pcoq.Constr.constr (* SSR plugin *)
+]
+
+ast_closure_term: [
+| term_annotation constr (* SSR plugin *)
+]
+
+ast_closure_lterm: [
+| term_annotation lconstr (* SSR plugin *)
+]
+
+ssrbwdview: [
+| test_not_ssrslashnum "/" Pcoq.Constr.constr (* SSR plugin *)
+| test_not_ssrslashnum "/" Pcoq.Constr.constr ssrbwdview (* SSR plugin *)
+]
+
+ssrfwdview: [
+| test_not_ssrslashnum "/" ast_closure_term (* SSR plugin *)
+| test_not_ssrslashnum "/" ast_closure_term ssrfwdview (* SSR plugin *)
+]
+
+ident_no_do: [
+| test_ident_no_do IDENT (* SSR plugin *)
+]
+
+ssripat: [
+| "_" (* SSR plugin *)
+| "*" (* SSR plugin *)
+| ">" (* SSR plugin *)
+| ident_no_do (* SSR plugin *)
+| "?" (* SSR plugin *)
+| "+" (* SSR plugin *)
+| "++" (* SSR plugin *)
+| ssrsimpl_ne (* SSR plugin *)
+| ssrdocc "->" (* SSR plugin *)
+| ssrdocc "<-" (* SSR plugin *)
+| ssrdocc (* SSR plugin *)
+| "->" (* SSR plugin *)
+| "<-" (* SSR plugin *)
+| "-" (* SSR plugin *)
+| "-/" "=" (* SSR plugin *)
+| "-/=" (* SSR plugin *)
+| "-/" "/" (* SSR plugin *)
+| "-//" (* SSR plugin *)
+| "-/" integer "/" (* SSR plugin *)
+| "-/" "/=" (* SSR plugin *)
+| "-//" "=" (* SSR plugin *)
+| "-//=" (* SSR plugin *)
+| "-/" integer "/=" (* SSR plugin *)
+| "-/" integer "/" integer "=" (* SSR plugin *)
+| ssrfwdview (* SSR plugin *)
+| "[" ":" LIST0 ident "]" (* SSR plugin *)
+| "[:" LIST0 ident "]" (* SSR plugin *)
+| ssrcpat (* SSR plugin *)
+]
+
+ssripats: [
+| ssripat ssripats (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssriorpat: [
+| ssripats "|" ssriorpat (* SSR plugin *)
+| ssripats "|-" ">" ssriorpat (* SSR plugin *)
+| ssripats "|-" ssriorpat (* SSR plugin *)
+| ssripats "|->" ssriorpat (* SSR plugin *)
+| ssripats "||" ssriorpat (* SSR plugin *)
+| ssripats "|||" ssriorpat (* SSR plugin *)
+| ssripats "||||" ssriorpat (* SSR plugin *)
+| ssripats (* SSR plugin *)
+]
+
+ssrcpat: [
+| test_nohidden "[" hat "]" (* SSR plugin *)
+| test_nohidden "[" ssriorpat "]" (* SSR plugin *)
+| test_nohidden "[=" ssriorpat "]" (* SSR plugin *)
+]
+
+hat: [
+| "^" ident (* SSR plugin *)
+| "^" "~" ident (* SSR plugin *)
+| "^" "~" natural (* SSR plugin *)
+| "^~" ident (* SSR plugin *)
+| "^~" natural (* SSR plugin *)
+]
+
+ssripats_ne: [
+| ssripat ssripats (* SSR plugin *)
+]
+
+ssrhpats: [
+| ssripats (* SSR plugin *)
+]
+
+ssrhpats_wtransp: [
+| ssripats (* SSR plugin *)
+| ssripats "@" ssripats (* SSR plugin *)
+]
+
+ssrhpats_nobs: [
+| ssripats (* SSR plugin *)
+]
+
+ssrrpat: [
+| "->" (* SSR plugin *)
+| "<-" (* SSR plugin *)
+]
+
+ssrintros_ne: [
+| "=>" ssripats_ne (* SSR plugin *)
+]
+
+ssrintros: [
+| ssrintros_ne (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrintrosarg: [
+]
+
+ssrfwdid: [
+| test_ssrfwdid Prim.ident (* SSR plugin *)
+]
+
+ssrortacs: [
+| ssrtacarg "|" ssrortacs (* SSR plugin *)
+| ssrtacarg "|" (* SSR plugin *)
+| ssrtacarg (* SSR plugin *)
+| "|" ssrortacs (* SSR plugin *)
+| "|" (* SSR plugin *)
+]
+
+ssrhintarg: [
+| "[" "]" (* SSR plugin *)
+| "[" ssrortacs "]" (* SSR plugin *)
+| ssrtacarg (* SSR plugin *)
+]
+
+ssrhint3arg: [
+| "[" "]" (* SSR plugin *)
+| "[" ssrortacs "]" (* SSR plugin *)
+| ssrtac3arg (* SSR plugin *)
+]
+
+ssrortacarg: [
+| "[" ssrortacs "]" (* SSR plugin *)
+]
+
+ssrhint: [
+| (* SSR plugin *)
+| "by" ssrhintarg (* SSR plugin *)
+]
+
+ssrwgen: [
+| ssrclear_ne (* SSR plugin *)
+| ssrhoi_hyp (* SSR plugin *)
+| "@" ssrhoi_hyp (* SSR plugin *)
+| "(" ssrhoi_id ":=" lcpattern ")" (* SSR plugin *)
+| "(" ssrhoi_id ")" (* SSR plugin *)
+| "(@" ssrhoi_id ":=" lcpattern ")" (* SSR plugin *)
+| "(" "@" ssrhoi_id ":=" lcpattern ")" (* SSR plugin *)
+]
+
+ssrclausehyps: [
+| ssrwgen "," ssrclausehyps (* SSR plugin *)
+| ssrwgen ssrclausehyps (* SSR plugin *)
+| ssrwgen (* SSR plugin *)
+]
+
+ssrclauses: [
+| "in" ssrclausehyps "|-" "*" (* SSR plugin *)
+| "in" ssrclausehyps "|-" (* SSR plugin *)
+| "in" ssrclausehyps "*" (* SSR plugin *)
+| "in" ssrclausehyps (* SSR plugin *)
+| "in" "|-" "*" (* SSR plugin *)
+| "in" "*" (* SSR plugin *)
+| "in" "*" "|-" (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrfwd: [
+| ":=" ast_closure_lterm (* SSR plugin *)
+| ":" ast_closure_lterm ":=" ast_closure_lterm (* SSR plugin *)
+]
+
+ssrbvar: [
+| ident (* SSR plugin *)
+| "_" (* SSR plugin *)
+]
+
+ssrbinder: [
+| ssrbvar (* SSR plugin *)
+| "(" ssrbvar ")" (* SSR plugin *)
+| "(" ssrbvar ":" lconstr ")" (* SSR plugin *)
+| "(" ssrbvar LIST1 ssrbvar ":" lconstr ")" (* SSR plugin *)
+| "(" ssrbvar ":" lconstr ":=" lconstr ")" (* SSR plugin *)
+| "(" ssrbvar ":=" lconstr ")" (* SSR plugin *)
+| [ "of" | "&" ] term99 (* SSR plugin *)
+]
+
+ssrstruct: [
+| "{" "struct" ident "}" (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrposefwd: [
+| LIST0 ssrbinder ssrfwd (* SSR plugin *)
+]
+
+ssrfixfwd: [
+| "fix" ssrbvar LIST0 ssrbinder ssrstruct ssrfwd (* SSR plugin *)
+]
+
+ssrcofixfwd: [
+| "cofix" ssrbvar LIST0 ssrbinder ssrfwd (* SSR plugin *)
+]
+
+ssrsetfwd: [
+| ":" ast_closure_lterm ":=" "{" ssrocc "}" cpattern (* SSR plugin *)
+| ":" ast_closure_lterm ":=" lcpattern (* SSR plugin *)
+| ":=" "{" ssrocc "}" cpattern (* SSR plugin *)
+| ":=" lcpattern (* SSR plugin *)
+]
+
+ssrhavefwd: [
+| ":" ast_closure_lterm ssrhint (* SSR plugin *)
+| ":" ast_closure_lterm ":=" ast_closure_lterm (* SSR plugin *)
+| ":" ast_closure_lterm ":=" (* SSR plugin *)
+| ":=" ast_closure_lterm (* SSR plugin *)
+]
+
+ssrhavefwdwbinders: [
+| ssrhpats_wtransp LIST0 ssrbinder ssrhavefwd (* SSR plugin *)
+]
+
+ssrdoarg: [
+]
+
+ssrseqarg: [
+| ssrswap (* SSR plugin *)
+| ssrseqidx ssrortacarg OPT ssrorelse (* SSR plugin *)
+| ssrseqidx ssrswap (* SSR plugin *)
+| ltac_expr3 (* SSR plugin *)
+]
+
+ssrseqidx: [
+| test_ssrseqvar Prim.ident (* SSR plugin *)
+| Prim.natural (* SSR plugin *)
+]
+
+ssrswap: [
+| "first" (* SSR plugin *)
+| "last" (* SSR plugin *)
+]
+
+ssrorelse: [
+| "||" ltac_expr2 (* SSR plugin *)
+]
+
+Prim.ident: [
+| IDENT ssr_null_entry (* SSR plugin *)
+]
+
+ssrparentacarg: [
+| "(" ltac_expr5 ")" (* SSR plugin *)
+]
+
+ssrdotac: [
+| ltac_expr3 (* SSR plugin *)
+| ssrortacarg (* SSR plugin *)
+]
+
+ssrseqdir: [
+]
+
+ssr_first: [
+| ssr_first ssrintros_ne (* SSR plugin *)
+| "[" LIST0 ltac_expr5 SEP "|" "]" (* SSR plugin *)
+]
+
+ssr_first_else: [
+| ssr_first ssrorelse (* SSR plugin *)
+| ssr_first (* SSR plugin *)
+]
+
+ssrgen: [
+| ssrdocc cpattern (* SSR plugin *)
+| cpattern (* SSR plugin *)
+]
+
+ssrdgens_tl: [
+| "{" LIST1 ssrhyp "}" cpattern ssrdgens_tl (* SSR plugin *)
+| "{" LIST1 ssrhyp "}" (* SSR plugin *)
+| "{" ssrocc "}" cpattern ssrdgens_tl (* SSR plugin *)
+| "/" ssrdgens_tl (* SSR plugin *)
+| cpattern ssrdgens_tl (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrdgens: [
+| ":" ssrgen ssrdgens_tl (* SSR plugin *)
+]
+
+ssreqid: [
+| test_ssreqid ssreqpat (* SSR plugin *)
+| test_ssreqid (* SSR plugin *)
+]
+
+ssreqpat: [
+| Prim.ident (* SSR plugin *)
+| "_" (* SSR plugin *)
+| "?" (* SSR plugin *)
+| "+" (* SSR plugin *)
+| ssrdocc "->" (* SSR plugin *)
+| ssrdocc "<-" (* SSR plugin *)
+| "->" (* SSR plugin *)
+| "<-" (* SSR plugin *)
+]
+
+ssrarg: [
+| ssrfwdview ssreqid ssrdgens ssrintros (* SSR plugin *)
+| ssrfwdview ssrclear ssrintros (* SSR plugin *)
+| ssreqid ssrdgens ssrintros (* SSR plugin *)
+| ssrclear_ne ssrintros (* SSR plugin *)
+| ssrintros_ne (* SSR plugin *)
+]
+
+ssrmovearg: [
+| ssrarg (* SSR plugin *)
+]
+
+ssrcasearg: [
+| ssrarg (* SSR plugin *)
+]
+
+ssragen: [
+| "{" LIST1 ssrhyp "}" ssrterm (* SSR plugin *)
+| ssrterm (* SSR plugin *)
+]
+
+ssragens: [
+| "{" LIST1 ssrhyp "}" ssrterm ssragens (* SSR plugin *)
+| "{" LIST1 ssrhyp "}" (* SSR plugin *)
+| ssrterm ssragens (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrapplyarg: [
+| ":" ssragen ssragens ssrintros (* SSR plugin *)
+| ssrclear_ne ssrintros (* SSR plugin *)
+| ssrintros_ne (* SSR plugin *)
+| ssrbwdview ":" ssragen ssragens ssrintros (* SSR plugin *)
+| ssrbwdview ssrclear ssrintros (* SSR plugin *)
+]
+
+ssrexactarg: [
+| ":" ssragen ssragens (* SSR plugin *)
+| ssrbwdview ssrclear (* SSR plugin *)
+| ssrclear_ne (* SSR plugin *)
+]
+
+ssrcongrarg: [
+| natural constr ssrdgens (* SSR plugin *)
+| natural constr (* SSR plugin *)
+| constr ssrdgens (* SSR plugin *)
+| constr (* SSR plugin *)
+]
+
+ssrrwocc: [
+| "{" LIST0 ssrhyp "}" (* SSR plugin *)
+| "{" ssrocc "}" (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrrule_ne: [
+| test_not_ssrslashnum [ "/" ssrterm | ssrterm | ssrsimpl_ne ] (* SSR plugin *)
+| ssrsimpl_ne (* SSR plugin *)
+]
+
+ssrrule: [
+| ssrrule_ne (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrpattern_squarep: [
+| "[" rpattern "]" (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrpattern_ne_squarep: [
+| "[" rpattern "]" (* SSR plugin *)
+]
+
+ssrrwarg: [
+| "-" ssrmult ssrrwocc ssrpattern_squarep ssrrule_ne (* SSR plugin *)
+| "-/" ssrterm (* SSR plugin *)
+| ssrmult_ne ssrrwocc ssrpattern_squarep ssrrule_ne (* SSR plugin *)
+| "{" LIST1 ssrhyp "}" ssrpattern_ne_squarep ssrrule_ne (* SSR plugin *)
+| "{" LIST1 ssrhyp "}" ssrrule (* SSR plugin *)
+| "{" ssrocc "}" ssrpattern_squarep ssrrule_ne (* SSR plugin *)
+| "{" "}" ssrpattern_squarep ssrrule_ne (* SSR plugin *)
+| ssrpattern_ne_squarep ssrrule_ne (* SSR plugin *)
+| ssrrule_ne (* SSR plugin *)
+]
+
+ssrrwargs: [
+| test_ssr_rw_syntax LIST1 ssrrwarg (* SSR plugin *)
+]
+
+ssrunlockarg: [
+| "{" ssrocc "}" ssrterm (* SSR plugin *)
+| ssrterm (* SSR plugin *)
+]
+
+ssrunlockargs: [
+| LIST0 ssrunlockarg (* SSR plugin *)
+]
+
+ssrsufffwd: [
+| ssrhpats LIST0 ssrbinder ":" ast_closure_lterm ssrhint (* SSR plugin *)
+]
+
+ssrwlogfwd: [
+| ":" LIST0 ssrwgen "/" ast_closure_lterm (* SSR plugin *)
+]
+
+ssr_idcomma: [
+| (* SSR plugin *)
+| test_idcomma [ IDENT | "_" ] "," (* SSR plugin *)
+]
+
+ssr_rtype: [
+| "return" term100 (* SSR plugin *)
+]
+
+ssr_mpat: [
+| pattern200 (* SSR plugin *)
+]
+
+ssr_dpat: [
+| ssr_mpat "in" pattern200 ssr_rtype (* SSR plugin *)
+| ssr_mpat ssr_rtype (* SSR plugin *)
+| ssr_mpat (* SSR plugin *)
+]
+
+ssr_dthen: [
+| ssr_dpat "then" lconstr (* SSR plugin *)
+]
+
+ssr_elsepat: [
+| "else" (* SSR plugin *)
+]
+
+ssr_else: [
+| ssr_elsepat lconstr (* SSR plugin *)
+]
+
+ssrhintref: [
+| constr (* SSR plugin *)
+| constr "|" natural (* SSR plugin *)
+]
+
+ssrviewpos: [
+| "for" "move" "/" (* SSR plugin *)
+| "for" "apply" "/" (* SSR plugin *)
+| "for" "apply" "/" "/" (* SSR plugin *)
+| "for" "apply" "//" (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssrviewposspc: [
+| ssrviewpos (* SSR plugin *)
+]
+
+rpattern: [
+| lconstr (* SSR plugin *)
+| "in" lconstr (* SSR plugin *)
+| lconstr "in" lconstr (* SSR plugin *)
+| "in" lconstr "in" lconstr (* SSR plugin *)
+| lconstr "in" lconstr "in" lconstr (* SSR plugin *)
+| lconstr "as" lconstr "in" lconstr (* SSR plugin *)
+]
+
+G_SSRMATCHING_cpattern: [
+| "Qed" constr (* SSR plugin *)
+| ssrtermkind constr (* SSR plugin *)
+]
+
+lcpattern: [
+| "Qed" lconstr (* SSR plugin *)
+| ssrtermkind lconstr (* SSR plugin *)
+]
+
+ssrpatternarg: [
+| rpattern (* SSR plugin *)
+]
+
+ssr_search_item: [
+| string (* SSR plugin *)
+| string "%" preident (* SSR plugin *)
+| constr_pattern (* SSR plugin *)
+]
+
+ssr_search_arg: [
+| "-" ssr_search_item ssr_search_arg (* SSR plugin *)
+| ssr_search_item ssr_search_arg (* SSR plugin *)
+| (* SSR plugin *)
+]
+
+ssr_modlocs: [
+| (* SSR plugin *)
+| "in" LIST1 modloc (* SSR plugin *)
+]
+
+modloc: [
+| "-" global (* SSR plugin *)
+| global (* SSR plugin *)
+]
+
+deprecated_number_modifier: [
|
| "(" "warning" "after" bignat ")"
| "(" "abstract" "after" bignat ")"
]
+number_string_mapping: [
+| reference "=>" reference
+| "[" reference "]" "=>" reference
+]
+
+number_string_via: [
+| "via" reference "mapping" "[" LIST1 number_string_mapping SEP "," "]"
+]
+
+number_modifier: [
+| "warning" "after" bignat
+| "abstract" "after" bignat
+| number_string_via
+]
+
+number_options: [
+| "(" LIST1 number_modifier SEP "," ")"
+]
+
+string_option: [
+| "(" number_string_via ")"
+]
+
tac2pat1: [
| Prim.qualid LIST1 tac2pat0 (* Ltac2 plugin *)
| Prim.qualid (* Ltac2 plugin *)
@@ -2586,6 +3258,7 @@ ltac2_expr5: [
| "fun" LIST1 G_LTAC2_input_fun "=>" ltac2_expr6 (* Ltac2 plugin *)
| "let" rec_flag LIST1 G_LTAC2_let_clause SEP "with" "in" ltac2_expr6 (* Ltac2 plugin *)
| "match" ltac2_expr5 "with" G_LTAC2_branches "end" (* Ltac2 plugin *)
+| "if" ltac2_expr5 "then" ltac2_expr5 "else" ltac2_expr5 (* Ltac2 plugin *)
| ltac2_expr4 (* Ltac2 plugin *)
]
diff --git a/doc/tools/docgram/orderedGrammar b/doc/tools/docgram/orderedGrammar
index 12a7bc684d..26474d950a 100644
--- a/doc/tools/docgram/orderedGrammar
+++ b/doc/tools/docgram/orderedGrammar
@@ -174,10 +174,129 @@ subsequent_letter: [
| [ first_letter | digit | "'" | unicode_id_part ]
]
-firstorder_rhs: [
-| OPT firstorder_using
-| "with" LIST1 ident
-| OPT firstorder_using "with" LIST1 ident
+ssrarg: [
+| OPT ssrfwdview OPT ssreqpat ssrdgens OPT ssrintros
+| ssrfwdview OPT ssrclear OPT ssrintros (* SSR plugin *)
+| ssrclear OPT ssrintros (* SSR plugin *)
+| ssrintros (* SSR plugin *)
+]
+
+ssreqpat: [
+| ident (* SSR plugin *)
+| "_" (* SSR plugin *)
+| "?" (* SSR plugin *)
+| "+" (* SSR plugin *)
+| ssrdocc "->" (* SSR plugin *)
+| ssrdocc "<-" (* SSR plugin *)
+| "->" (* SSR plugin *)
+| "<-" (* SSR plugin *)
+]
+
+ssrapplyarg: [
+| ssrclear OPT ssrintros (* SSR plugin *)
+| ssrintros (* SSR plugin *)
+| OPT ssrbwdview ":" ssragen OPT ssragens OPT ssrintros (* SSR plugin *)
+| ssrbwdview OPT ssrclear OPT ssrintros (* SSR plugin *)
+]
+
+ssragen: [
+| OPT ( "{" LIST1 ident "}" ) term (* SSR plugin *)
+]
+
+ssragens: [
+| "{" LIST1 ident "}" term OPT ssragens (* SSR plugin *)
+| "{" LIST1 ident "}" (* SSR plugin *)
+| term OPT ssragens (* SSR plugin *)
+]
+
+ssrintros: [
+| "=>" ssripats (* SSR plugin *)
+]
+
+ssrbwdview: [
+| "/" term (* SSR plugin *)
+| "/" term ssrbwdview (* SSR plugin *)
+]
+
+ssrdgens: [
+| ":" ssrgen OPT ( "/" ssrgen ) (* SSR plugin *)
+]
+
+ssrgen: [
+| cpattern LIST0 [ LIST1 ident | cpattern ] (* SSR plugin *)
+]
+
+rewrite_item: [
+| "-" OPT mult OPT occ_or_clear OPT ssrpattern_squarep r_item (* SSR plugin *)
+| mult OPT occ_or_clear OPT ssrpattern_squarep r_item (* SSR plugin *)
+| "-/" term (* SSR plugin *)
+| OPT ( OPT ( "{" LIST1 ident "}" ) ssrpattern_squarep ) r_item (* SSR plugin *)
+| "{" LIST1 ident "}" OPT r_item (* SSR plugin *)
+| "{" OPT ssr_occurrences "}" OPT ssrpattern_squarep r_item (* SSR plugin *)
+]
+
+occ_or_clear: [
+| clear_switch
+| "{" ssr_occurrences "}" (* SSR plugin *)
+]
+
+clear_switch: [
+| "{" LIST0 ident "}"
+]
+
+ssr_occurrences: [
+| [ natural | "+" | "-" ] LIST0 natural (* SSR plugin *)
+]
+
+r_item: [
+| [ OPT "/" term | s_item ] (* SSR plugin *)
+]
+
+ssrpattern_squarep: [
+| "[" rewrite_pattern "]" (* SSR plugin *)
+]
+
+rewrite_pattern: [
+| OPT ( OPT ( OPT ( OPT term "in" ) term ) "in" ) term (* SSR plugin *)
+| term "as" term "in" term (* SSR plugin *)
+]
+
+ssr_in: [
+| "in" ssrclausehyps OPT "|-" OPT "*" (* SSR plugin *)
+| "in" [ "*" | "*" "|-" | "|-" "*" ] (* SSR plugin *)
+]
+
+ssrclausehyps: [
+| gen_item LIST0 ( OPT "," gen_item ) (* SSR plugin *)
+]
+
+gen_item: [
+| ssrclear (* SSR plugin *)
+| OPT "@" ident (* SSR plugin *)
+| "(" ident OPT ( ":=" lcpattern ) ")" (* SSR plugin *)
+| "(@" ident ":=" lcpattern ")" (* SSR plugin *)
+]
+
+ssrclear: [
+| "{" LIST1 ident "}" (* SSR plugin *)
+]
+
+lcpattern: [
+| term
+]
+
+ssrsufffwd: [
+| OPT ssripats LIST0 ssrbinder ":" term OPT ( "by" ssrhintarg ) (* SSR plugin *)
+]
+
+ssrviewpos: [
+| "for" "move" "/" (* SSR plugin *)
+| "for" "apply" "/" (* SSR plugin *)
+| "for" "apply" "//" (* SSR plugin *)
+]
+
+ssr_one_term_pattern: [
+| one_term (* SSR plugin *)
]
where: [
@@ -347,9 +466,17 @@ term_if: [
| "if" term OPT [ OPT [ "as" name ] "return" term100 ] "then" term "else" term
]
+ssr_dpat: [
+| pattern OPT ( OPT ( "in" pattern ) "return" term100 ) (* SSR plugin *)
+]
+
term_let: [
| "let" name OPT ( ":" type ) ":=" term "in" term
| "let" name LIST1 binder OPT ( ":" type ) ":=" term "in" term
+| destructuring_let
+]
+
+destructuring_let: [
| "let" "(" LIST0 name SEP "," ")" OPT [ OPT [ "as" name ] "return" term100 ] ":=" term "in" term
| "let" "'" pattern ":=" term OPT ( "return" term100 ) "in" term
| "let" "'" pattern "in" pattern ":=" term "return" term100 "in" term
@@ -601,7 +728,11 @@ sort_family: [
]
hint_info: [
-| "|" OPT natural OPT one_term
+| "|" OPT natural OPT one_pattern
+]
+
+one_pattern: [
+| one_term
]
module_binder: [
@@ -884,9 +1015,11 @@ command: [
| "Print" "Rings" (* ring plugin *)
| "Add" "Field" ident ":" one_term OPT ( "(" LIST1 field_mod SEP "," ")" ) (* ring plugin *)
| "Print" "Fields" (* ring plugin *)
-| "Number" "Notation" qualid qualid qualid ":" scope_name OPT numeral_modifier
-| "Numeral" "Notation" qualid qualid qualid ":" scope_name OPT numeral_modifier
| "Hint" "Cut" "[" hints_path "]" OPT ( ":" LIST1 ident )
+| "Prenex" "Implicits" LIST1 qualid (* SSR plugin *)
+| "Print" "Hint" "View" OPT ssrviewpos (* SSR plugin *)
+| "Hint" "View" OPT ssrviewpos LIST1 ( one_term OPT ( "|" natural ) ) (* SSR plugin *)
+| "Search" OPT LIST1 ( "-" [ string OPT ( "%" ident ) | one_pattern ] ) OPT ( "in" LIST1 ( OPT "-" qualid ) ) (* SSR plugin *)
| "Typeclasses" "Transparent" LIST1 qualid
| "Typeclasses" "Opaque" LIST1 qualid
| "Typeclasses" "eauto" ":=" OPT "debug" OPT ( "(" [ "bfs" | "dfs" ] ")" ) OPT natural
@@ -910,7 +1043,9 @@ command: [
| "Derive" "Dependent" "Inversion_clear" ident "with" one_term "Sort" sort_family
| "Declare" "Left" "Step" one_term
| "Declare" "Right" "Step" one_term
-| "String" "Notation" qualid qualid qualid ":" scope_name
+| "Number" "Notation" qualid qualid qualid OPT ( "(" LIST1 number_modifier SEP "," ")" ) ":" scope_name
+| "Numeral" "Notation" qualid qualid qualid ":" scope_name OPT deprecated_number_modifier
+| "String" "Notation" qualid qualid qualid OPT ( "(" number_string_via ")" ) ":" scope_name
| "SubClass" ident_decl def_body
| thm_token ident_decl LIST0 binder ":" type LIST0 [ "with" ident_decl LIST0 binder ":" type ]
| assumption_token OPT ( "Inline" OPT ( "(" natural ")" ) ) [ LIST1 ( "(" assumpt ")" ) | assumpt ]
@@ -964,6 +1099,7 @@ command: [
| "Generalizable" [ [ "Variable" | "Variables" ] LIST1 ident | "All" "Variables" | "No" "Variables" ]
| "Set" setting_name OPT [ integer | string ]
| "Unset" setting_name
+| "Import" "Prenex" "Implicits" (* SSR plugin *)
| "Open" "Scope" scope
| "Close" "Scope" scope
| "Delimit" "Scope" scope_name "with" scope_key
@@ -979,9 +1115,9 @@ command: [
| "Compute" term
| "Check" term
| "About" reference OPT univ_name_list
-| "SearchHead" one_term OPT ( [ "inside" | "outside" ] LIST1 qualid )
-| "SearchPattern" one_term OPT ( [ "inside" | "outside" ] LIST1 qualid )
-| "SearchRewrite" one_term OPT ( [ "inside" | "outside" ] LIST1 qualid )
+| "SearchHead" one_pattern OPT ( [ "inside" | "outside" ] LIST1 qualid )
+| "SearchPattern" one_pattern OPT ( [ "inside" | "outside" ] LIST1 qualid )
+| "SearchRewrite" one_pattern OPT ( [ "inside" | "outside" ] LIST1 qualid )
| "Search" LIST1 ( search_query ) OPT ( [ "inside" | "outside" ] LIST1 qualid )
| "Ltac2" OPT "mutable" OPT "rec" tac2def_body LIST0 ( "with" tac2def_body )
| "Ltac2" "Type" OPT "rec" tac2typ_def LIST0 ( "with" tac2typ_def )
@@ -1039,7 +1175,7 @@ search_query: [
search_item: [
| OPT ( [ "head" | "hyp" | "concl" | "headhyp" | "headconcl" ] ":" ) string OPT ( "%" scope_key )
-| OPT ( [ "head" | "hyp" | "concl" | "headhyp" | "headconcl" ] ":" ) one_term
+| OPT ( [ "head" | "hyp" | "concl" | "headhyp" | "headconcl" ] ":" ) one_pattern
| "is" ":" logical_kind
]
@@ -1068,7 +1204,7 @@ hint: [
| "Mode" qualid LIST1 [ "+" | "!" | "-" ]
| "Unfold" LIST1 qualid
| "Constructors" LIST1 qualid
-| "Extern" natural OPT one_term "=>" ltac_expr
+| "Extern" natural OPT one_pattern "=>" ltac_expr
]
tacdef_body: [
@@ -1117,13 +1253,11 @@ lident: [
destruction_arg: [
| natural
-| one_term OPT ( "with" bindings )
| constr_with_bindings_arg
]
constr_with_bindings_arg: [
-| ">" one_term OPT ( "with" bindings )
-| one_term OPT ( "with" bindings )
+| OPT ">" one_term OPT ( "with" bindings ) (* SSR plugin *)
]
clause_dft_concl: [
@@ -1143,8 +1277,8 @@ hypident_occ: [
hypident: [
| ident
-| "(" "type" "of" ident ")"
-| "(" "value" "of" ident ")"
+| "(" "type" "of" ident ")" (* SSR plugin *)
+| "(" "value" "of" ident ")" (* SSR plugin *)
]
concl_occ: [
@@ -1269,11 +1403,133 @@ field_mod: [
| "completeness" one_term (* ring plugin *)
]
-numeral_modifier: [
+ssrmmod: [
+| "!" (* SSR plugin *)
+| "?" (* SSR plugin *)
+]
+
+mult: [
+| OPT natural ssrmmod (* SSR plugin *)
+]
+
+ssrwlogfwd: [
+| ":" LIST0 gen_item "/" term (* SSR plugin *)
+]
+
+ssrhintarg: [
+| "[" OPT ssrortacs "]" (* SSR plugin *)
+| ltac_expr (* SSR plugin *)
+]
+
+ssrortacs: [
+| OPT ltac_expr "|" OPT ssrortacs
+| ltac_expr (* SSR plugin *)
+]
+
+ssrhint3arg: [
+| "[" OPT ssrortacs "]" (* SSR plugin *)
+| ltac_expr3 (* SSR plugin *)
+]
+
+ssrdefbody: [
+| OPT ( ":" term ) ":=" term (* SSR plugin *)
+]
+
+i_item: [
+| "_" (* SSR plugin *)
+| "*" (* SSR plugin *)
+| ">" (* SSR plugin *)
+| ident
+| "?" (* SSR plugin *)
+| "+" (* SSR plugin *)
+| "++" (* SSR plugin *)
+| s_item (* SSR plugin *)
+| ssrdocc OPT [ "->" | "<-" ] (* SSR plugin *)
+| "-" (* SSR plugin *)
+| "-/=" (* SSR plugin *)
+| "-//" (* SSR plugin *)
+| "-//=" (* SSR plugin *)
+| "-/" integer [ "/=" | "/" | "/" integer "=" ] (* SSR plugin *)
+| ssrfwdview (* SSR plugin *)
+| "[:" LIST0 ident "]" (* SSR plugin *)
+| ssrblockpat (* SSR plugin *)
+]
+
+ssrhpats_wtransp: [
+| OPT ssripats (* SSR plugin *)
+| OPT ssripats "@" OPT ssripats (* SSR plugin *)
+]
+
+ssripats: [
+| LIST1 i_item (* SSR plugin *)
+]
+
+s_item: [
+| "//" (* SSR plugin *)
+| "/=" (* SSR plugin *)
+| "//=" (* SSR plugin *)
+| "/" natural "/" natural "=" (* SSR plugin *)
+| "/" natural "/=" (* SSR plugin *)
+]
+
+ssrdocc: [
+| "{" ssr_occurrences "}" (* SSR plugin *)
+| "{" LIST0 ident "}" (* SSR plugin *)
+]
+
+ssrfwdview: [
+| LIST1 ( "/" one_term ) (* SSR plugin *)
+]
+
+hat: [
+| "^" ident (* SSR plugin *)
+| "^~" ident (* SSR plugin *)
+| "^~" natural (* SSR plugin *)
+]
+
+ssriorpat: [
+| ssripats OPT ( [ "|" | "|-" ] ssriorpat ) (* SSR plugin *)
+]
+
+ssrblockpat: [
+| "[" hat "]" (* SSR plugin *)
+| "[" ssriorpat "]" (* SSR plugin *)
+| "[=" ssriorpat "]" (* SSR plugin *)
+]
+
+ssrbinder: [
+| ssrbvar (* SSR plugin *)
+| "(" LIST1 ssrbvar ":" term ")" (* SSR plugin *)
+| "(" ssrbvar OPT ( ":" term ) OPT ( ":=" term ) ")" (* SSR plugin *)
+| "of" term10 (* SSR plugin *)
+| "&" term10 (* SSR plugin *)
+]
+
+ssrbvar: [
+| ident (* SSR plugin *)
+| "_" (* SSR plugin *)
+]
+
+ssrhavefwd: [
+| ":" term OPT ( "by" ssrhintarg ) (* SSR plugin *)
+| ":" term ":=" OPT term (* SSR plugin *)
+]
+
+deprecated_number_modifier: [
| "(" "warning" "after" bignat ")"
| "(" "abstract" "after" bignat ")"
]
+number_modifier: [
+| "warning" "after" bignat
+| "abstract" "after" bignat
+| number_string_via
+]
+
+number_string_via: [
+| "via" qualid "mapping" "[" LIST1 [ qualid "=>" qualid | "[" qualid "]" "=>" qualid ] SEP "," "]"
+]
+
hints_path: [
| "(" hints_path ")"
| hints_path "*"
@@ -1392,11 +1648,14 @@ simple_tactic: [
| "infoH" ltac_expr3
| "abstract" ltac_expr2 OPT ( "using" ident )
| "only" selector ":" ltac_expr3
+| "do" "[" ssrortacs "]" OPT ssr_in (* SSR plugin *)
+| "do" OPT int_or_var ssrmmod [ ltac_expr3 | "[" ssrortacs "]" (* SSR plugin *) ] OPT ssr_in (* SSR plugin *)
| "tryif" ltac_expr "then" ltac_expr "else" ltac_expr2
| "first" "[" LIST0 ltac_expr SEP "|" "]"
| "solve" "[" LIST0 ltac_expr SEP "|" "]"
| "idtac" LIST0 [ ident | string | natural ]
| [ "fail" | "gfail" ] OPT int_or_var LIST0 [ ident | string | natural ]
+| ltac_expr ssrintros (* SSR plugin *)
| "fun" LIST1 name "=>" ltac_expr
| "eval" red_expr "in" term
| "context" ident "[" term "]"
@@ -1584,7 +1843,7 @@ simple_tactic: [
| "rtauto"
| "congruence" OPT natural OPT ( "with" LIST1 one_term )
| "f_equal"
-| "firstorder" OPT ltac_expr firstorder_rhs
+| "firstorder" OPT ltac_expr OPT ( "using" LIST1 qualid SEP "," ) OPT ( "with" LIST1 ident )
| "gintuition" OPT ltac_expr
| "functional" "inversion" [ ident | natural ] OPT qualid (* funind plugin *)
| "functional" "induction" term OPT ( "using" one_term OPT ( "with" bindings ) ) OPT ( "as" simple_intropattern ) (* funind plugin *)
@@ -1611,12 +1870,47 @@ simple_tactic: [
| "protect_fv" string OPT ( "in" ident )
| "ring_lookup" ltac_expr0 "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *)
| "field_lookup" ltac_expr "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *)
+| "ring_lookup" ltac_expr0 "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *)
+| "field_lookup" ltac_expr "[" LIST0 one_term "]" LIST1 one_term (* ring plugin *)
+| "by" ssrhintarg (* SSR plugin *)
+| "clear" natural (* SSR plugin *)
+| "move" OPT ( OPT ssrarg [ "->" | "<-" ] ) (* SSR plugin *)
+| "move" ssrarg OPT ssr_in (* SSR plugin *)
+| "case" OPT ( ssrarg OPT ssr_in ) (* SSR plugin *)
+| "elim" OPT ( ssrarg OPT ssr_in ) (* SSR plugin *)
+| "apply" OPT ssrapplyarg (* SSR plugin *)
+| "exact" [ ":" ssragen OPT ssragens | ssrbwdview OPT ssrclear | ssrclear ] (* SSR plugin *)
+| "exact" (* SSR plugin *)
+| "exact" "<:" term (* SSR plugin *)
+| "congr" OPT natural one_term OPT ssrdgens (* SSR plugin *)
+| "ssrinstancesofruleL2R" term (* SSR plugin *)
+| "ssrinstancesofruleR2L" term (* SSR plugin *)
+| "rewrite" LIST1 rewrite_item OPT ssr_in (* SSR plugin *)
+| "unlock" LIST0 ( OPT ( "{" ssr_occurrences "}" ) term ) OPT ssr_in (* SSR plugin *)
+| "pose" "fix" ssrbvar LIST0 ssrbinder OPT ( "{" "struct" ident "}" ) ssrdefbody (* SSR plugin *)
+| "pose" "cofix" ssrbvar LIST0 ssrbinder ssrdefbody (* SSR plugin *)
+| "pose" ident LIST0 ssrbinder ssrdefbody (* SSR plugin *)
+| "set" ident OPT ( ":" term ) ":=" [ "{" ssr_occurrences "}" cpattern | lcpattern ] OPT ssr_in (* SSR plugin *)
+| "abstract" ssrdgens (* SSR plugin *)
+| "have" ssrhpats_wtransp LIST0 ssrbinder ssrhavefwd (* SSR plugin *)
+| "have" [ "suff" | "suffices" ] OPT ssripats ssrhavefwd (* SSR plugin *)
+| [ "suff" | "suffices" ] OPT ( "have" OPT ssripats ) ssrhavefwd (* SSR plugin *)
+| [ "suff" | "suffices" ] ssrsufffwd (* SSR plugin *)
+| [ "wlog" | "without loss" ] OPT [ "suff" | "suffices" ] OPT ssripats ssrwlogfwd OPT ( "by" ssrhintarg ) (* SSR plugin *)
+| [ "gen" | "generally" ] "have" OPT ssrclear OPT ( [ ident | "_" ] "," ) OPT ssripats ssrwlogfwd OPT ( "by" ssrhintarg ) (* SSR plugin *)
+| "under" rewrite_item OPT ssrintros OPT ( "do" ssrhint3arg ) (* SSR plugin *)
+| "ssrinstancesoftpat" ssr_one_term_pattern (* SSR plugin *)
+| ltac_expr ";" "first" ssr_first_else (* SSR plugin *)
+| ltac_expr ";" "first" ssrseqarg (* SSR plugin *)
+| ltac_expr ";" "last" ssrseqarg (* SSR plugin *)
| match_key OPT "reverse" "goal" "with" OPT "|" LIST1 ( goal_pattern "=>" ltac_expr ) SEP "|" "end"
| match_key ltac_expr "with" OPT "|" LIST1 ( match_pattern "=>" ltac_expr ) SEP "|" "end"
| "classical_left"
| "classical_right"
| "contradict" ident
+| "dintuition" OPT ltac_expr
| "discrR"
+| "dtauto"
| "easy"
| "exfalso"
| "inversion_sigma"
@@ -1624,6 +1918,7 @@ simple_tactic: [
| "lra"
| "nia"
| "nra"
+| "over" (* SSR plugin *)
| "split_Rabs"
| "split_Rmult"
| "tauto"
@@ -1640,6 +1935,7 @@ simple_tactic: [
| "ring" OPT ( "[" LIST1 one_term "]" )
| "ring_simplify" OPT ( "[" LIST1 one_term "]" ) LIST1 one_term OPT ( "in" ident )
| "match" ltac2_expr5 "with" OPT ltac2_branches "end"
+| "if" ltac2_expr5 "then" ltac2_expr5 "else" ltac2_expr5
| qualid LIST1 tactic_arg
]
@@ -1673,20 +1969,25 @@ as_name: [
| "as" ident
]
+oriented_rewriter: [
+| OPT [ "->" | "<-" ] rewriter
+]
+
rewriter: [
| OPT natural OPT [ "?" | "!" ] constr_with_bindings_arg
]
-oriented_rewriter: [
-| OPT [ "->" | "<-" ] rewriter
+induction_clause_list: [
+| LIST1 induction_clause SEP "," OPT ( "using" one_term OPT ( "with" bindings ) ) OPT opt_clause
]
induction_clause: [
| destruction_arg OPT as_or_and_ipat OPT eqn_ipat OPT opt_clause
]
-induction_clause_list: [
-| LIST1 induction_clause SEP "," OPT ( "using" one_term OPT ( "with" bindings ) ) OPT opt_clause
+opt_clause: [
+| "in" in_clause
+| "at" occs_nums
]
auto_using: [
@@ -1825,7 +2126,7 @@ q_rewriting: [
]
ltac2_oriented_rewriter: [
-| [ "->" | "<-" ] ltac2_rewriter (* Ltac2 plugin *)
+| OPT [ "->" | "<-" ] ltac2_rewriter (* Ltac2 plugin *)
]
ltac2_rewriter: [
@@ -2111,9 +2412,9 @@ tac2mode: [
| "Compute" term
| "Check" term
| "About" reference OPT univ_name_list
-| "SearchHead" one_term OPT ( [ "inside" | "outside" ] LIST1 qualid )
-| "SearchPattern" one_term OPT ( [ "inside" | "outside" ] LIST1 qualid )
-| "SearchRewrite" one_term OPT ( [ "inside" | "outside" ] LIST1 qualid )
+| "SearchHead" one_pattern OPT ( [ "inside" | "outside" ] LIST1 qualid )
+| "SearchPattern" one_pattern OPT ( [ "inside" | "outside" ] LIST1 qualid )
+| "SearchRewrite" one_pattern OPT ( [ "inside" | "outside" ] LIST1 qualid )
| "Search" LIST1 ( search_query ) OPT ( [ "inside" | "outside" ] LIST1 qualid )
]
@@ -2121,11 +2422,6 @@ clause_dft_all: [
| "in" in_clause
]
-opt_clause: [
-| "in" in_clause
-| "at" occs_nums
-]
-
in_hyp_as: [
| "in" ident OPT as_ipat
]
@@ -2153,12 +2449,6 @@ conversion: [
| one_term "at" occs_nums "with" one_term
]
-firstorder_using: [
-| "using" qualid
-| "using" qualid "," LIST1 qualid SEP ","
-| "using" qualid qualid LIST0 qualid
-]
-
func_scheme_def: [
| ident ":=" "Induction" "for" qualid "Sort" sort_family (* funind plugin *)
]
@@ -2264,6 +2554,34 @@ tactic_atom: [
| "()"
]
+ssrseqarg: [
+| ssrseqidx "[" ssrortacs "]" OPT ssrorelse (* SSR plugin *)
+| OPT ssrseqidx ssrswap (* SSR plugin *)
+| ltac_expr3 (* SSR plugin *)
+]
+
+ssrseqidx: [
+| ident (* SSR plugin *)
+| natural (* SSR plugin *)
+]
+
+ssrorelse: [
+| "||" ltac_expr2 (* SSR plugin *)
+]
+
+ssrswap: [
+| "first" (* SSR plugin *)
+| "last" (* SSR plugin *)
+]
+
+ssr_first_else: [
+| ssr_first OPT ssrorelse (* SSR plugin *)
+]
+
+ssr_first: [
+| "[" LIST0 ltac_expr SEP "|" "]" LIST0 ssrintros (* SSR plugin *)
+]
+
let_clause: [
| name ":=" ltac_expr
| ident LIST1 name ":=" ltac_expr
diff --git a/engine/eConstr.ml b/engine/eConstr.ml
index 374cb72753..c29de27efb 100644
--- a/engine/eConstr.ml
+++ b/engine/eConstr.ml
@@ -452,6 +452,9 @@ let eq_universes env sigma cstrs cv_pb refargs l l' =
let open GlobRef in
let open UnivProblem in
match refargs with
+ | Some (ConstRef c, 1) when Environ.is_array_type env c ->
+ cstrs := compare_cumulative_instances cv_pb true [|Univ.Variance.Irrelevant|] l l' !cstrs;
+ true
| None | Some (ConstRef _, _) ->
cstrs := enforce_eq_instances_univs true l l' !cstrs; true
| Some (VarRef _, _) -> assert false (* variables don't have instances *)
@@ -563,6 +566,9 @@ let universes_of_constr sigma c =
| Array (u,_,_,_) ->
let s = LSet.fold LSet.add (Instance.levels (EInstance.kind sigma u)) s in
fold sigma aux s c
+ | Case (_,_,CaseInvert {univs;args=_},_,_) ->
+ let s = LSet.fold LSet.add (Instance.levels (EInstance.kind sigma univs)) s in
+ fold sigma aux s c
| _ -> fold sigma aux s c
in aux LSet.empty c
@@ -625,6 +631,9 @@ let subst_var subst c = of_constr (Vars.subst_var subst (to_constr c))
let subst_univs_level_constr subst c =
of_constr (Vars.subst_univs_level_constr subst (to_constr c))
+let subst_univs_constr subst c =
+ of_constr (UnivSubst.subst_univs_constr subst (to_constr c))
+
(** Operations that dot NOT commute with evar-normalization *)
let noccurn sigma n term =
let rec occur_rec n c = match kind sigma c with
diff --git a/engine/eConstr.mli b/engine/eConstr.mli
index a018f4064f..882dfe2848 100644
--- a/engine/eConstr.mli
+++ b/engine/eConstr.mli
@@ -295,6 +295,7 @@ val closedn : Evd.evar_map -> int -> t -> bool
val closed0 : Evd.evar_map -> t -> bool
val subst_univs_level_constr : Univ.universe_level_subst -> t -> t
+val subst_univs_constr : Univ.universe_subst -> t -> t
val subst_of_rel_context_instance : rel_context -> t list -> t list
diff --git a/engine/evarutil.ml b/engine/evarutil.ml
index 771571fd3f..ba6a9ea6d9 100644
--- a/engine/evarutil.ml
+++ b/engine/evarutil.ml
@@ -371,7 +371,8 @@ let push_rel_decl_to_named_context
let subst = update_var id0 id subst in
let d = decl |> NamedDecl.of_rel_decl (fun _ -> id0) |> map_decl (csubst_subst subst) in
let nc = replace_var_named_declaration id0 id nc in
- (push_var id0 subst, Id.Set.add id avoid, push_named_context_val d nc)
+ let avoid = Id.Set.add id (Id.Set.add id0 avoid) in
+ (push_var id0 subst, avoid, push_named_context_val d nc)
| Some id0 when hypnaming = FailIfConflict ->
user_err Pp.(Id.print id0 ++ str " is already used.")
| _ ->
diff --git a/engine/evd.ml b/engine/evd.ml
index 4ae1d034d7..498a9d9825 100644
--- a/engine/evd.ml
+++ b/engine/evd.ml
@@ -832,9 +832,9 @@ let empty = {
extras = Store.empty;
}
-let from_env e = { empty with universes = UState.from_env e }
+let from_env ?binders e = { empty with universes = UState.from_env ?binders e }
-let from_ctx ctx = { empty with universes = ctx }
+let from_ctx uctx = { empty with universes = uctx }
let has_undefined evd = not (EvMap.is_empty evd.undf_evars)
diff --git a/engine/evd.mli b/engine/evd.mli
index fafaad9a04..1c5c65924c 100644
--- a/engine/evd.mli
+++ b/engine/evd.mli
@@ -153,12 +153,18 @@ type evar_map
val empty : evar_map
(** The empty evar map. *)
-val from_env : env -> evar_map
+val from_env : ?binders:lident list -> env -> evar_map
(** The empty evar map with given universe context, taking its initial
- universes from env. *)
+ universes from env, possibly with initial universe binders. This
+ is the main entry point at the beginning of the process of
+ interpreting a declaration (e.g. before entering the
+ interpretation of a Theorem statement). *)
val from_ctx : UState.t -> evar_map
-(** The empty evar map with given universe context *)
+(** The empty evar map with given universe context. This is the main
+ entry point when resuming from a already interpreted declaration
+ (e.g. after having interpreted a Theorem statement and preparing
+ to open a goal). *)
val is_empty : evar_map -> bool
(** Whether an evarmap is empty. *)
diff --git a/engine/uState.ml b/engine/uState.ml
index 9557111cfd..103b552d86 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -25,8 +25,8 @@ module UPairSet = UnivMinim.UPairSet
(* 2nd part used to check consistency on the fly. *)
type t =
- { names : UnivNames.universe_binders * uinfo LMap.t;
- local : ContextSet.t; (** The local context of variables *)
+ { names : UnivNames.universe_binders * uinfo LMap.t; (** Printing/location information *)
+ local : ContextSet.t; (** The local graph of universes (variables and constraints) *)
seff_univs : LSet.t; (** Local universes used through private constants *)
univ_variables : UnivSubst.universe_opt_subst;
(** The local universes that are unification variables *)
@@ -56,18 +56,16 @@ let elaboration_sprop_cumul =
Goptions.declare_bool_option_and_ref ~depr:false
~key:["Elaboration";"StrictProp";"Cumulativity"] ~value:true
-let make ~lbound u =
- let u = UGraph.set_cumulative_sprop (elaboration_sprop_cumul ()) u in
+let make ~lbound univs =
+ let univs = UGraph.set_cumulative_sprop (elaboration_sprop_cumul ()) univs in
{ empty with
- universes = u;
+ universes = univs;
universes_lbound = lbound;
- initial_universes = u}
+ initial_universes = univs}
-let from_env e = make ~lbound:(Environ.universes_lbound e) (Environ.universes e)
-
-let is_empty ctx =
- ContextSet.is_empty ctx.local &&
- LMap.is_empty ctx.univ_variables
+let is_empty uctx =
+ ContextSet.is_empty uctx.local &&
+ LMap.is_empty uctx.univ_variables
let uname_union s t =
if s == t then s
@@ -77,42 +75,42 @@ let uname_union s t =
| Some _, _ -> l
| _, _ -> r) s t
-let union ctx ctx' =
- if ctx == ctx' then ctx
- else if is_empty ctx' then ctx
+let union uctx uctx' =
+ if uctx == uctx' then uctx
+ else if is_empty uctx' then uctx
else
- let local = ContextSet.union ctx.local ctx'.local in
- let seff = LSet.union ctx.seff_univs ctx'.seff_univs in
- let names = uname_union (fst ctx.names) (fst ctx'.names) in
- let newus = LSet.diff (ContextSet.levels ctx'.local)
- (ContextSet.levels ctx.local) in
- let newus = LSet.diff newus (LMap.domain ctx.univ_variables) in
- let weak = UPairSet.union ctx.weak_constraints ctx'.weak_constraints in
+ let local = ContextSet.union uctx.local uctx'.local in
+ let seff = LSet.union uctx.seff_univs uctx'.seff_univs in
+ let names = uname_union (fst uctx.names) (fst uctx'.names) in
+ let names_rev = LMap.lunion (snd uctx.names) (snd uctx'.names) in
+ let newus = LSet.diff (ContextSet.levels uctx'.local)
+ (ContextSet.levels uctx.local) in
+ let newus = LSet.diff newus (LMap.domain uctx.univ_variables) in
+ let weak = UPairSet.union uctx.weak_constraints uctx'.weak_constraints in
let declarenew g =
- LSet.fold (fun u g -> UGraph.add_universe u ~lbound:ctx.universes_lbound ~strict:false g) newus g
+ LSet.fold (fun u g -> UGraph.add_universe u ~lbound:uctx.universes_lbound ~strict:false g) newus g
in
- let names_rev = LMap.lunion (snd ctx.names) (snd ctx'.names) in
{ names = (names, names_rev);
local = local;
seff_univs = seff;
univ_variables =
- LMap.subst_union ctx.univ_variables ctx'.univ_variables;
+ LMap.subst_union uctx.univ_variables uctx'.univ_variables;
univ_algebraic =
- LSet.union ctx.univ_algebraic ctx'.univ_algebraic;
- initial_universes = declarenew ctx.initial_universes;
+ LSet.union uctx.univ_algebraic uctx'.univ_algebraic;
+ initial_universes = declarenew uctx.initial_universes;
universes =
- (if local == ctx.local then ctx.universes
+ (if local == uctx.local then uctx.universes
else
- let cstrsr = ContextSet.constraints ctx'.local in
- UGraph.merge_constraints cstrsr (declarenew ctx.universes));
- universes_lbound = ctx.universes_lbound;
+ let cstrsr = ContextSet.constraints uctx'.local in
+ UGraph.merge_constraints cstrsr (declarenew uctx.universes));
+ universes_lbound = uctx.universes_lbound;
weak_constraints = weak}
-let context_set ctx = ctx.local
+let context_set uctx = uctx.local
-let constraints ctx = snd ctx.local
+let constraints uctx = snd uctx.local
-let context ctx = ContextSet.to_context ctx.local
+let context uctx = ContextSet.to_context uctx.local
let compute_instance_binders inst ubinders =
let revmap = Id.Map.fold (fun id lvl accu -> LMap.add lvl id accu) ubinders LMap.empty in
@@ -131,15 +129,15 @@ let univ_entry ~poly uctx =
Polymorphic_entry (nas, uctx)
else Monomorphic_entry (context_set uctx)
-let of_context_set ctx = { empty with local = ctx }
+let of_context_set local = { empty with local }
-let subst ctx = ctx.univ_variables
+let subst uctx = uctx.univ_variables
-let ugraph ctx = ctx.universes
+let ugraph uctx = uctx.universes
-let initial_graph ctx = ctx.initial_universes
+let initial_graph uctx = uctx.initial_universes
-let algebraics ctx = ctx.univ_algebraic
+let algebraics uctx = uctx.univ_algebraic
let add_names ?loc s l (names, names_rev) =
if UNameMap.mem s names
@@ -152,14 +150,13 @@ let add_loc l loc (names, names_rev) =
| None -> (names, names_rev)
| Some _ -> (names, LMap.add l { uname = None; uloc = loc } names_rev)
-let of_binders b =
- let ctx = empty in
- let rmap =
+let of_binders names =
+ let rev_map =
UNameMap.fold (fun id l rmap ->
LMap.add l { uname = Some id; uloc = None } rmap)
- b LMap.empty
+ names LMap.empty
in
- { ctx with names = b, rmap }
+ { empty with names = (names, rev_map) }
let invent_name (named,cnt) u =
let rec aux i =
@@ -169,14 +166,14 @@ let invent_name (named,cnt) u =
in
aux cnt
-let universe_binders ctx =
- let named, rev = ctx.names in
+let universe_binders uctx =
+ let named, rev = uctx.names in
let named, _ = LSet.fold (fun u named ->
match LMap.find u rev with
| exception Not_found -> (* not sure if possible *) invent_name named u
| { uname = None } -> invent_name named u
| { uname = Some _ } -> named)
- (ContextSet.levels ctx.local) (named, 0)
+ (ContextSet.levels uctx.local) (named, 0)
in
named
@@ -192,12 +189,12 @@ let drop_weak_constraints =
~key:["Cumulativity";"Weak";"Constraints"]
~value:false
-let process_universe_constraints ctx cstrs =
+let process_universe_constraints uctx cstrs =
let open UnivSubst in
let open UnivProblem in
- let univs = ctx.universes in
- let vars = ref ctx.univ_variables in
- let weak = ref ctx.weak_constraints in
+ let univs = uctx.universes in
+ let vars = ref uctx.univ_variables in
+ let weak = ref uctx.weak_constraints in
let normalize u = normalize_univ_variable_opt_subst !vars u in
let nf_constraint = function
| ULub (u, v) -> ULub (level_subst_of normalize u, level_subst_of normalize v)
@@ -231,7 +228,7 @@ let process_universe_constraints ctx cstrs =
let equalize_universes l r local = match varinfo l, varinfo r with
| Inr l', Inr r' -> equalize_variables false l l' r r' local
| Inr l, Inl r | Inl r, Inr l ->
- let alg = LSet.mem l ctx.univ_algebraic in
+ let alg = LSet.mem l uctx.univ_algebraic in
let inst = univ_level_rem l r r in
if alg && not (LSet.mem l (Universe.levels inst)) then
(instantiate_variable l inst vars; local)
@@ -295,8 +292,8 @@ let process_universe_constraints ctx cstrs =
in
!vars, !weak, local
-let add_constraints ctx cstrs =
- let univs, local = ctx.local in
+let add_constraints uctx cstrs =
+ let univs, old_cstrs = uctx.local in
let cstrs' = Constraint.fold (fun (l,d,r) acc ->
let l = Universe.make l and r = Universe.make r in
let cstr' = let open UnivProblem in
@@ -308,27 +305,27 @@ let add_constraints ctx cstrs =
in UnivProblem.Set.add cstr' acc)
cstrs UnivProblem.Set.empty
in
- let vars, weak, local' = process_universe_constraints ctx cstrs' in
- { ctx with
- local = (univs, Constraint.union local local');
+ let vars, weak, cstrs' = process_universe_constraints uctx cstrs' in
+ { uctx with
+ local = (univs, Constraint.union old_cstrs cstrs');
univ_variables = vars;
- universes = UGraph.merge_constraints local' ctx.universes;
+ universes = UGraph.merge_constraints cstrs' uctx.universes;
weak_constraints = weak; }
(* let addconstrkey = CProfile.declare_profile "add_constraints_context";; *)
(* let add_constraints_context = CProfile.profile2 addconstrkey add_constraints_context;; *)
-let add_universe_constraints ctx cstrs =
- let univs, local = ctx.local in
- let vars, weak, local' = process_universe_constraints ctx cstrs in
- { ctx with
+let add_universe_constraints uctx cstrs =
+ let univs, local = uctx.local in
+ let vars, weak, local' = process_universe_constraints uctx cstrs in
+ { uctx with
local = (univs, Constraint.union local local');
univ_variables = vars;
- universes = UGraph.merge_constraints local' ctx.universes;
+ universes = UGraph.merge_constraints local' uctx.universes;
weak_constraints = weak; }
-let constrain_variables diff ctx =
- let univs, local = ctx.local in
+let constrain_variables diff uctx =
+ let univs, local = uctx.local in
let univs, vars, local =
LSet.fold
(fun l (univs, vars, cstrs) ->
@@ -340,9 +337,9 @@ let constrain_variables diff ctx =
Constraint.add (l, Eq, Option.get (Universe.level u)) cstrs)
| None -> (univs, vars, cstrs)
with Not_found | Option.IsNone -> (univs, vars, cstrs))
- diff (univs, ctx.univ_variables, local)
+ diff (univs, uctx.univ_variables, local)
in
- { ctx with local = (univs, local); univ_variables = vars }
+ { uctx with local = (univs, local); univ_variables = vars }
let qualid_of_level uctx =
let map, map_rev = uctx.names in
@@ -403,8 +400,8 @@ let universe_context ~names ~extensible uctx =
let left = ContextSet.sort_levels (Array.of_list (LSet.elements left)) in
let inst = Array.append (Array.of_list newinst) left in
let inst = Instance.of_array inst in
- let ctx = UContext.make (inst, ContextSet.constraints uctx.local) in
- ctx
+ let uctx = UContext.make (inst, ContextSet.constraints uctx.local) in
+ uctx
let check_universe_context_set ~names ~extensible uctx =
if extensible then ()
@@ -439,27 +436,24 @@ let check_mono_univ_decl uctx decl =
uctx.local
let check_univ_decl ~poly uctx decl =
- let ctx =
- let names = decl.univdecl_instance in
- let extensible = decl.univdecl_extensible_instance in
- if poly then
- let (binders, _) = uctx.names in
- let uctx = universe_context ~names ~extensible uctx in
- let nas = compute_instance_binders (UContext.instance uctx) binders in
- Entries.Polymorphic_entry (nas, uctx)
- else
- let () = check_universe_context_set ~names ~extensible uctx in
- Entries.Monomorphic_entry uctx.local
- in
if not decl.univdecl_extensible_constraints then
check_implication uctx
decl.univdecl_constraints
(ContextSet.constraints uctx.local);
- ctx
+ let names = decl.univdecl_instance in
+ let extensible = decl.univdecl_extensible_instance in
+ if poly then
+ let (binders, _) = uctx.names in
+ let uctx = universe_context ~names ~extensible uctx in
+ let nas = compute_instance_binders (UContext.instance uctx) binders in
+ Entries.Polymorphic_entry (nas, uctx)
+ else
+ let () = check_universe_context_set ~names ~extensible uctx in
+ Entries.Monomorphic_entry uctx.local
let is_bound l lbound = match lbound with
-| UGraph.Bound.Prop -> Level.is_prop l
-| UGraph.Bound.Set -> Level.is_set l
+ | UGraph.Bound.Prop -> Level.is_prop l
+ | UGraph.Bound.Set -> Level.is_set l
let restrict_universe_context ~lbound (univs, csts) keep =
let removed = LSet.diff univs keep in
@@ -476,13 +470,13 @@ let restrict_universe_context ~lbound (univs, csts) keep =
not ((is_bound l lbound && d == Le) || (Level.is_prop l && d == Lt && Level.is_set r))) csts in
(LSet.inter univs keep, csts)
-let restrict ctx vars =
- let vars = LSet.union vars ctx.seff_univs in
+let restrict uctx vars =
+ let vars = LSet.union vars uctx.seff_univs in
let vars = Names.Id.Map.fold (fun na l vars -> LSet.add l vars)
- (fst ctx.names) vars
+ (fst uctx.names) vars
in
- let uctx' = restrict_universe_context ~lbound:ctx.universes_lbound ctx.local vars in
- { ctx with local = uctx' }
+ let uctx' = restrict_universe_context ~lbound:uctx.universes_lbound uctx.local vars in
+ { uctx with local = uctx' }
type rigid =
| UnivRigid
@@ -498,8 +492,8 @@ let univ_flexible_alg = UnivFlexible true
context we merge comes from a side effect that is already inlined
or defined separately. In the later case, there is no extension,
see [emit_side_effects] for example. *)
-let merge ?loc ~sideff rigid uctx ctx' =
- let levels = ContextSet.levels ctx' in
+let merge ?loc ~sideff rigid uctx uctx' =
+ let levels = ContextSet.levels uctx' in
let uctx =
match rigid with
| UnivRigid -> uctx
@@ -514,7 +508,7 @@ let merge ?loc ~sideff rigid uctx ctx' =
univ_algebraic = LSet.union uctx.univ_algebraic levels }
else { uctx with univ_variables = uvars' }
in
- let local = ContextSet.append ctx' uctx.local in
+ let local = ContextSet.append uctx' uctx.local in
let declare g =
LSet.fold (fun u g ->
try UGraph.add_universe ~lbound:uctx.universes_lbound ~strict:false u g
@@ -534,7 +528,7 @@ let merge ?loc ~sideff rigid uctx ctx' =
in
let initial = declare uctx.initial_universes in
let univs = declare uctx.universes in
- let universes = UGraph.merge_constraints (ContextSet.constraints ctx') univs in
+ let universes = UGraph.merge_constraints (ContextSet.constraints uctx') univs in
{ uctx with names; local; universes;
initial_universes = initial }
@@ -553,19 +547,18 @@ let demote_global_univs env uctx =
ContextSet.(of_set global_univs |> add_constraints global_constraints) in
{ uctx with local = ContextSet.diff uctx.local promoted_uctx }
-let merge_seff uctx ctx' =
- let levels = ContextSet.levels ctx' in
+let merge_seff uctx uctx' =
+ let levels = ContextSet.levels uctx' in
let declare g =
LSet.fold (fun u g ->
try UGraph.add_universe ~lbound:uctx.universes_lbound ~strict:false u g
with UGraph.AlreadyDeclared -> g)
levels g
in
- let initial = declare uctx.initial_universes in
+ let initial_universes = declare uctx.initial_universes in
let univs = declare uctx.universes in
- let universes = UGraph.merge_constraints (ContextSet.constraints ctx') univs in
- { uctx with universes;
- initial_universes = initial }
+ let universes = UGraph.merge_constraints (ContextSet.constraints uctx') univs in
+ { uctx with universes; initial_universes }
let emit_side_effects eff u =
let uctx = Safe_typing.universes_of_private eff in
@@ -581,60 +574,54 @@ let update_sigma_univs uctx ugraph =
in
merge_seff eunivs eunivs.local
-let new_univ_variable ?loc rigid name
- ({ local = ctx; univ_variables = uvars; univ_algebraic = avars} as uctx) =
- let u = UnivGen.fresh_level () in
- let ctx' = ContextSet.add_universe u ctx in
- let uctx', pred =
- match rigid with
- | UnivRigid -> uctx, true
- | UnivFlexible b ->
- let uvars' = LMap.add u None uvars in
- if b then {uctx with univ_variables = uvars';
- univ_algebraic = LSet.add u avars}, false
- else {uctx with univ_variables = uvars'}, false
- in
+let add_universe ?loc name strict lbound uctx u =
+ let initial_universes = UGraph.add_universe ~lbound ~strict u uctx.initial_universes in
+ let universes = UGraph.add_universe ~lbound ~strict u uctx.universes in
+ let local = ContextSet.add_universe u uctx.local in
let names =
match name with
| Some n -> add_names ?loc n u uctx.names
| None -> add_loc u loc uctx.names
in
- let initial =
- UGraph.add_universe ~lbound:uctx.universes_lbound ~strict:false u uctx.initial_universes
+ { uctx with names; local; initial_universes; universes }
+
+let new_univ_variable ?loc rigid name uctx =
+ let u = UnivGen.fresh_level () in
+ let uctx =
+ match rigid with
+ | UnivRigid -> uctx
+ | UnivFlexible allow_alg ->
+ let univ_variables = LMap.add u None uctx.univ_variables in
+ if allow_alg
+ then
+ let univ_algebraic = LSet.add u uctx.univ_algebraic in
+ { uctx with univ_variables; univ_algebraic }
+ else
+ { uctx with univ_variables }
in
- let uctx' =
- {uctx' with names = names; local = ctx';
- universes = UGraph.add_universe ~lbound:uctx.universes_lbound ~strict:false
- u uctx.universes;
- initial_universes = initial}
- in uctx', u
-
-let make_with_initial_binders ~lbound e us =
- let uctx = make ~lbound e in
+ let uctx = add_universe ?loc name false uctx.universes_lbound uctx u in
+ uctx, u
+
+let add_global_univ uctx u = add_universe None true UGraph.Bound.Set uctx u
+
+let make_with_initial_binders ~lbound univs us =
+ let uctx = make ~lbound univs in
List.fold_left
(fun uctx { CAst.loc; v = id } ->
fst (new_univ_variable ?loc univ_rigid (Some id) uctx))
uctx us
-let add_global_univ uctx u =
- let initial =
- UGraph.add_universe ~lbound:UGraph.Bound.Set ~strict:true u uctx.initial_universes
- in
- let univs =
- UGraph.add_universe ~lbound:UGraph.Bound.Set ~strict:true u uctx.universes
- in
- { uctx with local = ContextSet.add_universe u uctx.local;
- initial_universes = initial;
- universes = univs }
+let from_env ?(binders=[]) env =
+ make_with_initial_binders ~lbound:(Environ.universes_lbound env) (Environ.universes env) binders
-let make_flexible_variable ctx ~algebraic u =
+let make_flexible_variable uctx ~algebraic u =
let {local = cstrs; univ_variables = uvars;
- univ_algebraic = avars; universes=g; } = ctx in
+ univ_algebraic = avars; universes=g; } = uctx in
assert (try LMap.find u uvars == None with Not_found -> true);
match UGraph.choose (fun v -> not (Level.equal u v) && (algebraic || not (LSet.mem v avars))) g u with
| Some v ->
let uvars' = LMap.add u (Some (Universe.make v)) uvars in
- { ctx with univ_variables = uvars'; }
+ { uctx with univ_variables = uvars'; }
| None ->
let uvars' = LMap.add u None uvars in
let avars' =
@@ -652,14 +639,13 @@ let make_flexible_variable ctx ~algebraic u =
then LSet.add u avars else avars
else avars
in
- {ctx with univ_variables = uvars';
- univ_algebraic = avars'}
+ { uctx with univ_variables = uvars'; univ_algebraic = avars' }
-let make_nonalgebraic_variable ctx u =
- { ctx with univ_algebraic = LSet.remove u ctx.univ_algebraic }
+let make_nonalgebraic_variable uctx u =
+ { uctx with univ_algebraic = LSet.remove u uctx.univ_algebraic }
-let make_flexible_nonalgebraic ctx =
- {ctx with univ_algebraic = LSet.empty}
+let make_flexible_nonalgebraic uctx =
+ { uctx with univ_algebraic = LSet.empty }
let is_sort_variable uctx s =
match s with
@@ -671,8 +657,8 @@ let is_sort_variable uctx s =
| None -> None)
| _ -> None
-let subst_univs_context_with_def def usubst (ctx, cst) =
- (LSet.diff ctx def, UnivSubst.subst_univs_constraints usubst cst)
+let subst_univs_context_with_def def usubst (uctx, cst) =
+ (LSet.diff uctx def, UnivSubst.subst_univs_constraints usubst cst)
let is_trivial_leq (l,d,r) =
Level.is_prop l && (d == Le || d == Lt) && Level.is_set r
@@ -696,9 +682,9 @@ let normalize_variables uctx =
let normalized_variables, def, subst =
UnivSubst.normalize_univ_variables uctx.univ_variables
in
- let ctx_local = subst_univs_context_with_def def (make_subst subst) uctx.local in
- let ctx_local', univs = refresh_constraints uctx.initial_universes ctx_local in
- subst, { uctx with local = ctx_local';
+ let uctx_local = subst_univs_context_with_def def (make_subst subst) uctx.local in
+ let uctx_local', univs = refresh_constraints uctx.initial_universes uctx_local in
+ subst, { uctx with local = uctx_local';
univ_variables = normalized_variables;
universes = univs }
diff --git a/engine/uState.mli b/engine/uState.mli
index 7fec03e3b2..bd3aac0d8b 100644
--- a/engine/uState.mli
+++ b/engine/uState.mli
@@ -23,25 +23,34 @@ type t
(** {5 Constructors} *)
+(** Different ways to create a new universe state *)
+
val empty : t
val make : lbound:UGraph.Bound.t -> UGraph.t -> t
+[@@ocaml.deprecated "Use from_env"]
val make_with_initial_binders : lbound:UGraph.Bound.t -> UGraph.t -> lident list -> t
+[@@ocaml.deprecated "Use from_env"]
-val from_env : Environ.env -> t
-
-val is_empty : t -> bool
+val from_env : ?binders:lident list -> Environ.env -> t
+(** Main entry point at the beginning of a declaration declaring the
+ binding names as rigid universes. *)
-val union : t -> t -> t
+val of_binders : UnivNames.universe_binders -> t
+(** Main entry point when only names matter, e.g. for printing. *)
val of_context_set : Univ.ContextSet.t -> t
+(** Main entry point when starting from the instance of a global
+ reference, e.g. when building a scheme. *)
-val of_binders : UnivNames.universe_binders -> t
+(** Misc *)
-val universe_binders : t -> UnivNames.universe_binders
+val is_empty : t -> bool
+
+val union : t -> t -> t
-(** {5 Projections} *)
+(** {5 Projections and other destructors} *)
val context_set : t -> Univ.ContextSet.t
(** The local context of the state, i.e. a set of bound variables together
@@ -69,6 +78,9 @@ val context : t -> Univ.UContext.t
val univ_entry : poly:bool -> t -> Entries.universes_entry
(** Pick from {!context} or {!context_set} based on [poly]. *)
+val universe_binders : t -> UnivNames.universe_binders
+(** Return names of universes, inventing names if needed *)
+
(** {5 Constraints handling} *)
val add_constraints : t -> Univ.Constraint.t -> t
@@ -115,7 +127,7 @@ val emit_side_effects : Safe_typing.private_constants -> t -> t
val demote_global_univs : Environ.env -> t -> t
(** Removes from the uctx_local part of the UState the universes and constraints
that are present in the universe graph in the input env (supposedly the
- global ones *)
+ global ones) *)
val demote_seff_univs : Univ.LSet.t -> t -> t
(** Mark the universes as not local any more, because they have been
@@ -123,6 +135,11 @@ val demote_seff_univs : Univ.LSet.t -> t -> t
emit_side_effects instead. *)
val new_univ_variable : ?loc:Loc.t -> rigid -> Id.t option -> t -> t * Univ.Level.t
+(** Declare a new local universe; use rigid if a global or bound
+ universe; use flexible for a universe existential variable; use
+ univ_flexible_alg for a universe existential variable allowed to
+ be instantiated with an algebraic universe *)
+
val add_global_univ : t -> Univ.Level.t -> t
(** [make_flexible_variable g algebraic l]
diff --git a/ide/coqide/coq.ml b/ide/coqide/coq.ml
index 1167b8199e..b8228df2aa 100644
--- a/ide/coqide/coq.ml
+++ b/ide/coqide/coq.ml
@@ -550,6 +550,7 @@ struct
let existential = BoolOpt ["Printing"; "Existential"; "Instances"]
let universes = BoolOpt ["Printing"; "Universes"]
let unfocused = BoolOpt ["Printing"; "Unfocused"]
+ let goal_names = BoolOpt ["Printing"; "Goal"; "Names"]
let diff = StringOpt ["Diffs"]
type 'a descr = { opts : 'a t list; init : 'a; label : string }
@@ -568,7 +569,8 @@ struct
{ opts = [universes]; init = false; label = "Display _universe levels" };
{ opts = [all_basic;existential;universes]; init = false;
label = "Display all _low-level contents" };
- { opts = [unfocused]; init = false; label = "Display _unfocused goals" }
+ { opts = [unfocused]; init = false; label = "Display _unfocused goals" };
+ { opts = [goal_names]; init = false; label = "Display _goal names" }
]
let diff_item = { opts = [diff]; init = "off"; label = "Display _proof diffs" }
diff --git a/ide/coqide/coqide_ui.ml b/ide/coqide/coqide_ui.ml
index 6540fc6fca..badfabf07e 100644
--- a/ide/coqide/coqide_ui.ml
+++ b/ide/coqide/coqide_ui.ml
@@ -85,6 +85,7 @@ let init () =
\n <menuitem action='Display universe levels' />\
\n <menuitem action='Display all low-level contents' />\
\n <menuitem action='Display unfocused goals' />\
+\n <menuitem action='Display goal names' />\
\n <separator/>\
\n <menuitem action='Unset diff' />\
\n <menuitem action='Set diff' />\
diff --git a/ide/coqide/idetop.ml b/ide/coqide/idetop.ml
index ddfa3a80bd..602acefa7c 100644
--- a/ide/coqide/idetop.ml
+++ b/ide/coqide/idetop.ml
@@ -195,7 +195,7 @@ let concl_next_tac =
let process_goal sigma g =
let env = Goal.V82.env sigma g in
let min_env = Environ.reset_context env in
- let id = Goal.uid g in
+ let id = if Printer.print_goal_names () then Names.Id.to_string (Termops.evar_suggested_name g sigma) else "" in
let ccl =
pr_letype_env ~goal_concl_style:true env sigma (Goal.V82.concl sigma g)
in
@@ -206,7 +206,7 @@ let process_goal sigma g =
let (_env, hyps) =
Context.Compacted.fold process_hyp
(Termops.compact_named_context (Environ.named_context env)) ~init:(min_env,[]) in
- { Interface.goal_hyp = List.rev hyps; Interface.goal_ccl = ccl; Interface.goal_id = id; }
+ { Interface.goal_hyp = List.rev hyps; Interface.goal_ccl = ccl; Interface.goal_id = id }
let process_goal_diffs diff_goal_map oldp nsigma ng =
let open Evd in
diff --git a/ide/coqide/wg_ProofView.ml b/ide/coqide/wg_ProofView.ml
index 1de63953af..8e451c9917 100644
--- a/ide/coqide/wg_ProofView.ml
+++ b/ide/coqide/wg_ProofView.ml
@@ -52,7 +52,7 @@ let hook_tag_cb tag menu_content sel_cb hover_cb =
let mode_tactic sel_cb (proof : #GText.view_skel) goals ~unfoc_goals hints = match goals with
| [] -> assert false
- | { Interface.goal_hyp = hyps; Interface.goal_ccl = cur_goal; } :: rem_goals ->
+ | { Interface.goal_hyp = hyps; Interface.goal_ccl = cur_goal; Interface.goal_id = cur_id } :: rem_goals ->
let on_hover sel_start sel_stop =
proof#buffer#remove_tag
~start:proof#buffer#start_iter
@@ -68,11 +68,11 @@ let mode_tactic sel_cb (proof : #GText.view_skel) goals ~unfoc_goals hints = mat
let head_str = Printf.sprintf
"%d subgoal%s\n" goals_cnt (if 1 < goals_cnt then "s" else "")
in
- let goal_str ?(shownum=false) index total =
- if shownum then Printf.sprintf
- "______________________________________(%d/%d)\n" index total
- else Printf.sprintf
- "______________________________________\n"
+ let goal_str ?(shownum=false) index total id =
+ let annot =
+ if CString.is_empty id then if shownum then Printf.sprintf "(%d/%d)" index total else ""
+ else Printf.sprintf "(?%s)" id in
+ Printf.sprintf "______________________________________%s\n" annot
in
(* Insert current goal and its hypotheses *)
let hyps_hints, goal_hints = match hints with
@@ -103,13 +103,13 @@ let mode_tactic sel_cb (proof : #GText.view_skel) goals ~unfoc_goals hints = mat
[tag]
else []
in
- proof#buffer#insert (goal_str ~shownum:true 1 goals_cnt);
+ proof#buffer#insert (goal_str ~shownum:true 1 goals_cnt cur_id);
insert_xml ~tags:[Tags.Proof.goal] proof#buffer (Richpp.richpp_of_pp width cur_goal);
proof#buffer#insert "\n"
in
(* Insert remaining goals (no hypotheses) *)
- let fold_goal ?(shownum=false) i _ { Interface.goal_ccl = g } =
- proof#buffer#insert (goal_str ~shownum i goals_cnt);
+ let fold_goal ?(shownum=false) i _ { Interface.goal_ccl = g; Interface.goal_id = id } =
+ proof#buffer#insert (goal_str ~shownum i goals_cnt id);
insert_xml proof#buffer (Richpp.richpp_of_pp width g);
proof#buffer#insert "\n"
in
@@ -178,12 +178,16 @@ let display mode (view : #GText.view_skel) goals hints evars =
| _, _, _, _ ->
(* No foreground proofs, but still unfocused ones *)
let total = List.length bg in
- let goal_str index = Printf.sprintf
- "______________________________________(%d/%d)\n" index total
+ let goal_str index id =
+ let annot =
+ if CString.is_empty id then Printf.sprintf "(%d/%d)" index total
+ else Printf.sprintf "(?%s)" id in
+ Printf.sprintf
+ "______________________________________%s\n" annot
in
view#buffer#insert "This subproof is complete, but there are some unfocused goals:\n\n";
let iter i goal =
- let () = view#buffer#insert (goal_str (succ i)) in
+ let () = view#buffer#insert (goal_str (succ i) goal.Interface.goal_id) in
insert_xml view#buffer (Richpp.richpp_of_pp width goal.Interface.goal_ccl);
view#buffer#insert "\n"
in
diff --git a/interp/constrexpr.ml b/interp/constrexpr.ml
index d14d156ffc..235310660b 100644
--- a/interp/constrexpr.ml
+++ b/interp/constrexpr.ml
@@ -58,7 +58,7 @@ type abstraction_kind = AbsLambda | AbsPi
type proj_flag = int option (** [Some n] = proj of the n-th visible argument *)
type prim_token =
- | Numeral of NumTok.Signed.t
+ | Number 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 7075d082ee..efc2a35b65 100644
--- a/interp/constrexpr_ops.ml
+++ b/interp/constrexpr_ops.ml
@@ -44,13 +44,13 @@ let names_of_local_binders bl =
(**********************************************************************)
(* Functions on constr_expr *)
-(* Note: redundant Numeral representations, such as -0 and +0 (and others),
+(* Note: redundant Number representations, such as -0 and +0 (and others),
are considered different here. *)
let prim_token_eq t1 t2 = match t1, t2 with
-| Numeral n1, Numeral n2 -> NumTok.Signed.equal n1 n2
+| Number n1, Number n2 -> NumTok.Signed.equal n1 n2
| String s1, String s2 -> String.equal s1 s2
-| (Numeral _ | String _), _ -> false
+| (Number _ | String _), _ -> false
let explicitation_eq ex1 ex2 = match ex1, ex2 with
| ExplByPos (i1, id1), ExplByPos (i2, id2) ->
@@ -614,37 +614,3 @@ let rec coerce_to_cases_pattern_expr c = CAst.map_with_loc (fun ?loc -> function
| _ ->
CErrors.user_err ?loc ~hdr:"coerce_to_cases_pattern_expr"
(str "This expression should be coercible to a pattern.")) c
-
-(** Local universe and constraint declarations. *)
-
-let interp_univ_constraints env evd cstrs =
- let interp (evd,cstrs) (u, d, u') =
- let ul = Pretyping.interp_known_glob_level evd u in
- let u'l = Pretyping.interp_known_glob_level evd u' in
- let cstr = (ul,d,u'l) in
- let cstrs' = Univ.Constraint.add cstr cstrs in
- try let evd = Evd.add_constraints evd (Univ.Constraint.singleton cstr) in
- evd, cstrs'
- with Univ.UniverseInconsistency e as exn ->
- let _, info = Exninfo.capture exn in
- CErrors.user_err ~hdr:"interp_constraint" ~info
- (Univ.explain_universe_inconsistency (Termops.pr_evd_level evd) e)
- in
- List.fold_left interp (evd,Univ.Constraint.empty) cstrs
-
-let interp_univ_decl env decl =
- let open UState in
- let pl : lident list = decl.univdecl_instance in
- let evd = Evd.from_ctx (UState.make_with_initial_binders ~lbound:(Environ.universes_lbound env)
- (Environ.universes env) pl) in
- let evd, cstrs = interp_univ_constraints env evd decl.univdecl_constraints in
- let decl = { univdecl_instance = pl;
- univdecl_extensible_instance = decl.univdecl_extensible_instance;
- univdecl_constraints = cstrs;
- univdecl_extensible_constraints = decl.univdecl_extensible_constraints }
- in evd, decl
-
-let interp_univ_decl_opt env l =
- match l with
- | None -> Evd.from_env env, UState.default_univ_decl
- | Some decl -> interp_univ_decl env decl
diff --git a/interp/constrexpr_ops.mli b/interp/constrexpr_ops.mli
index edf52c93e8..dfa51918d1 100644
--- a/interp/constrexpr_ops.mli
+++ b/interp/constrexpr_ops.mli
@@ -123,10 +123,3 @@ val patntn_loc : ?loc:Loc.t -> cases_pattern_notation_substitution -> notation -
(** For cases pattern parsing errors *)
val error_invalid_pattern_notation : ?loc:Loc.t -> unit -> 'a
-
-(** Local universe and constraint declarations. *)
-val interp_univ_decl : Environ.env -> universe_decl_expr ->
- Evd.evar_map * UState.universe_decl
-
-val interp_univ_decl_opt : Environ.env -> universe_decl_expr option ->
- Evd.evar_map * UState.universe_decl
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 7bf1c58148..d1bec16a3f 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -357,18 +357,18 @@ let destPatPrim = function { CAst.v = CPatPrim t } -> Some t | _ -> None
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 p)] when not (NumTok.Signed.is_zero p) ->
+ | "- _", [Some (Number p)] when not (NumTok.Signed.is_zero p) ->
assert (bl=[]);
mknot (loc,ntn,([mknot (loc,(InConstrEntry,"( _ )"),l,[])]),[])
| _ ->
match decompose_notation_key ntn, l with
| (InConstrEntry,[Terminal "-"; Terminal x]), [] ->
begin match NumTok.Unsigned.parse_string x with
- | Some n -> mkprim (loc, Numeral (NumTok.SMinus,n))
+ | Some n -> mkprim (loc, Number (NumTok.SMinus,n))
| None -> mknot (loc,ntn,l,bl) end
| (InConstrEntry,[Terminal x]), [] ->
begin match NumTok.Unsigned.parse_string x with
- | Some n -> mkprim (loc, Numeral (NumTok.SPlus,n))
+ | Some n -> mkprim (loc, Number (NumTok.SPlus,n))
| None -> mknot (loc,ntn,l,bl) end
| _ -> mknot (loc,ntn,l,bl)
@@ -915,7 +915,7 @@ let extern_float f scopes =
let hex = !Flags.raw_print || not (get_printing_float ()) in
if hex then Float64.to_hex_string f else Float64.to_string f in
let n = NumTok.Signed.of_string s in
- extern_prim_token_delimiter_if_required (Numeral n)
+ extern_prim_token_delimiter_if_required (Number n)
"float" "float_scope" scopes
(**********************************************************************)
@@ -1097,7 +1097,7 @@ let rec extern inctx ?impargs scopes vars r =
| GInt i ->
extern_prim_token_delimiter_if_required
- (Numeral (NumTok.Signed.of_int_string (Uint63.to_string i)))
+ (Number (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 959b61a3d7..06cf19b4f7 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -263,6 +263,13 @@ type intern_env = {
binder_block_names: (abstraction_kind option (* None = unknown *) * Id.Set.t) option;
}
+type pattern_intern_env = {
+ pat_scopes: Notation_term.subscopes;
+ (* ids = Some means accept local variables; this is useful for
+ terms as patterns parsed as pattersn in notations *)
+ pat_ids: Id.Set.t option;
+}
+
(**********************************************************************)
(* Remembering the parsing scope of variables in notations *)
@@ -317,6 +324,9 @@ let reset_tmp_scope env = {env with tmp_scope = None}
let set_env_scopes env (scopt,subscopes) =
{env with tmp_scope = scopt; scopes = subscopes @ env.scopes}
+let env_for_pattern env =
+ {pat_scopes = (env.tmp_scope, env.scopes); pat_ids = Some env.ids}
+
let mkGProd ?loc (na,bk,t) body = DAst.make ?loc @@ GProd (na, bk, t, body)
let mkGLambda ?loc (na,bk,t) body = DAst.make ?loc @@ GLambda (na, bk, t, body)
@@ -420,6 +430,40 @@ let binder_status_fun = {
slide = on_snd slide_binders;
}
+(* [test_kind_strict] rules out pattern which refers to global other
+ than constructors or variables; It is used in instances of notations *)
+
+let test_kind_pattern_in_notation ?loc = function
+ | GlobRef.ConstructRef _ -> ()
+ (* We do not accept non constructors to be used as variables in
+ patterns *)
+ | GlobRef.ConstRef _ ->
+ user_err ?loc (str "Found a constant while a pattern was expected.")
+ | GlobRef.IndRef _ ->
+ user_err ?loc (str "Found an inductive type while a pattern was expected.")
+ | GlobRef.VarRef _ ->
+ (* we accept a section variable name to be used as pattern variable *)
+ raise Not_found
+
+let test_kind_ident_in_notation ?loc = function
+ | GlobRef.ConstructRef _ ->
+ user_err ?loc (str "Found a constructor while a variable name was expected.")
+ | GlobRef.ConstRef _ ->
+ user_err ?loc (str "Found a constant while a variable name was expected.")
+ | GlobRef.IndRef _ ->
+ user_err ?loc (str "Found an inductive type while a variable name was expected.")
+ | GlobRef.VarRef _ ->
+ (* we accept a section variable name to be used as pattern variable *)
+ raise Not_found
+
+(* [test_kind_tolerant] allow global reference names to be used as pattern variables *)
+
+let test_kind_tolerant ?loc = function
+ | GlobRef.ConstructRef _ -> ()
+ | GlobRef.ConstRef _ | GlobRef.IndRef _ | GlobRef.VarRef _ ->
+ (* A non-constructor global reference in a pattern is seen as a variable *)
+ raise Not_found
+
(**)
let locate_if_hole ?loc na c = match DAst.get c with
@@ -539,9 +583,9 @@ let intern_letin_binder intern ntnvars env (({loc;v=na} as locna),def,ty) =
(push_name_env ntnvars impls env locna,
(na,Explicit,term,ty))
-let intern_cases_pattern_as_binder ?loc ntnvars env p =
+let intern_cases_pattern_as_binder ?loc test_kind ntnvars env p =
let il,disjpat =
- let (il, subst_disjpat) = !intern_cases_pattern_fwd ntnvars (None,env.scopes) p in
+ let (il, subst_disjpat) = !intern_cases_pattern_fwd test_kind ntnvars (env_for_pattern (reset_tmp_scope env)) p in
let substl,disjpat = List.split subst_disjpat in
if not (List.for_all (fun subst -> Id.Map.equal Id.equal subst Id.Map.empty) substl) then
user_err ?loc (str "Unsupported nested \"as\" clause.");
@@ -568,7 +612,7 @@ let intern_local_binder_aux intern ntnvars (env,bl) = function
| Some ty -> ty
| None -> CAst.make ?loc @@ CHole(None,IntroAnonymous,None)
in
- let env, ((disjpat,il),id),na = intern_cases_pattern_as_binder ?loc ntnvars env p in
+ let env, ((disjpat,il),id),na = intern_cases_pattern_as_binder ?loc test_kind_tolerant ntnvars env p in
let bk = Default Explicit in
let _, bl' = intern_assumption intern ntnvars env [na] bk tyc in
let {v=(_,bk,t)} = List.hd bl' in
@@ -661,27 +705,21 @@ let is_patvar_store store pat =
| PatVar na -> ignore(store na); true
| _ -> false
-let out_patvar pat =
- match pat.v with
+let out_patvar = CAst.map_with_loc (fun ?loc -> function
| CPatAtom (Some qid) when qualid_is_ident qid ->
Name (qualid_basename qid)
| CPatAtom None -> Anonymous
- | _ -> assert false
-
-let term_of_name = function
- | Name id -> DAst.make (GVar id)
- | Anonymous ->
- let st = Evar_kinds.Define (not (Program.get_proofs_transparency ())) in
- DAst.make (GHole (Evar_kinds.QuestionMark { Evar_kinds.default_question_mark with Evar_kinds.qm_obligation=st }, IntroAnonymous, None))
+ | _ -> assert false)
let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renaming,env) = function
| Anonymous -> (renaming,env), None, Anonymous
| Name id ->
let store,get = set_temporary_memory () in
+ let test_kind = test_kind_tolerant in
try
(* We instantiate binder name with patterns which may be parsed as terms *)
let pat = coerce_to_cases_pattern_expr (fst (Id.Map.find id terms)) in
- let env,((disjpat,ids),id),na = intern_pat ntnvars env pat in
+ let env,((disjpat,ids),id),na = intern_pat test_kind ntnvars env pat in
let pat, na = match disjpat with
| [pat] when is_patvar_store store pat -> let na = get () in None, na
| _ -> Some ((List.map (fun x -> x.v) ids,disjpat),id), na.v in
@@ -694,11 +732,11 @@ let traverse_binder intern_pat ntnvars (terms,_,binders,_ as subst) avoid (renam
if onlyident then
(* Do not try to interpret a variable as a constructor *)
let na = out_patvar pat in
- let env = push_name_env ntnvars [] env (make ?loc:pat.loc na) in
- (renaming,env), None, na
+ let env = push_name_env ntnvars [] env na in
+ (renaming,env), None, na.v
else
(* Interpret as a pattern *)
- let env,((disjpat,ids),id),na = intern_pat ntnvars env pat in
+ let env,((disjpat,ids),id),na = intern_pat test_kind ntnvars env pat in
let pat, na =
match disjpat with
| [pat] when is_patvar_store store pat -> let na = get () in None, na
@@ -829,22 +867,22 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
let arg = match arg with
| None -> None
| Some arg ->
- let mk_env id (c, (tmp_scope, subscopes)) map =
- let nenv = {env with tmp_scope; scopes = subscopes @ env.scopes} in
+ let mk_env id (c, scopes) map =
+ let nenv = set_env_scopes env scopes in
try
let gc = intern nenv c in
Id.Map.add id (gc, None) map
with Nametab.GlobalizationError _ -> map
in
- let mk_env' (c, (onlyident,(tmp_scope,subscopes))) =
- let nenv = {env with tmp_scope; scopes = subscopes @ env.scopes} in
- if onlyident then
- let na = out_patvar c in term_of_name na, None
- else
- let _,((disjpat,_),_),_ = intern_pat ntnvars nenv c in
- match disjpat with
- | [pat] -> (glob_constr_of_cases_pattern (Global.env()) pat, None)
- | _ -> error_cannot_coerce_disjunctive_pattern_term ?loc:c.loc ()
+ let mk_env' (c, (onlyident,scopes)) =
+ let nenv = set_env_scopes env scopes in
+ let test_kind =
+ if onlyident then test_kind_ident_in_notation
+ else test_kind_pattern_in_notation in
+ let _,((disjpat,_),_),_ = intern_pat test_kind ntnvars nenv c in
+ match disjpat with
+ | [pat] -> (glob_constr_of_cases_pattern (Global.env()) pat, None)
+ | _ -> error_cannot_coerce_disjunctive_pattern_term ?loc:c.loc ()
in
let terms = Id.Map.fold mk_env terms Id.Map.empty in
let binders = Id.Map.map mk_env' binders in
@@ -890,20 +928,19 @@ let instantiate_notation_constr loc intern intern_pat ntnvars subst infos c =
(* subst remembers the delimiters stack in the interpretation *)
(* of the notations *)
try
- let (a,(scopt,subscopes)) = Id.Map.find id terms in
- intern {env with tmp_scope = scopt;
- scopes = subscopes @ env.scopes} a
+ let (a,scopes) = Id.Map.find id terms in
+ intern (set_env_scopes env scopes) a
with Not_found ->
try
let pat,(onlyident,scopes) = Id.Map.find id binders in
- let env = set_env_scopes env scopes in
- if onlyident then
- term_of_name (out_patvar pat)
- else
- let env,((disjpat,ids),id),na = intern_pat ntnvars env pat in
- match disjpat with
- | [pat] -> glob_constr_of_cases_pattern (Global.env()) pat
- | _ -> user_err Pp.(str "Cannot turn a disjunctive pattern into a term.")
+ let nenv = set_env_scopes env scopes in
+ let test_kind =
+ if onlyident then test_kind_ident_in_notation
+ else test_kind_pattern_in_notation in
+ let env,((disjpat,ids),id),na = intern_pat test_kind ntnvars nenv pat in
+ match disjpat with
+ | [pat] -> glob_constr_of_cases_pattern (Global.env()) pat
+ | _ -> user_err Pp.(str "Cannot turn a disjunctive pattern into a term.")
with Not_found ->
try
match binderopt with
@@ -1570,11 +1607,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 p) } -> not (NumTok.Signed.is_zero p)
+| { CAst.v = CPrim (Number p) } -> not (NumTok.Signed.is_zero p)
| _ -> false
let is_non_zero_pat c = match c with
-| { CAst.v = CPatPrim (Numeral p) } -> not (NumTok.Signed.is_zero p)
+| { CAst.v = CPatPrim (Number p) } -> not (NumTok.Signed.is_zero p)
| _ -> false
let get_asymmetric_patterns = Goptions.declare_bool_option_and_ref
@@ -1582,19 +1619,14 @@ let get_asymmetric_patterns = Goptions.declare_bool_option_and_ref
~key:["Asymmetric";"Patterns"]
~value:false
-let drop_notations_pattern looked_for genv =
+let drop_notations_pattern (test_kind_top,test_kind_inner) genv env pat =
(* At toplevel, Constructors and Inductives are accepted, in recursive calls
only constructor are allowed *)
- let ensure_kind top loc g =
- try
- if top then looked_for g else
- match g with GlobRef.ConstructRef _ -> () | _ -> raise Not_found
+ let ensure_kind test_kind ?loc g =
+ try test_kind ?loc g
with Not_found ->
error_invalid_pattern_notation ?loc ()
in
- let test_kind top =
- if top then looked_for else function GlobRef.ConstructRef _ -> () | _ -> raise Not_found
- in
(* [rcp_of_glob] : from [glob_constr] to [raw_cases_pattern_expr] *)
let rec rcp_of_glob scopes x = DAst.(map (function
| GVar id -> RCPatAtom (Some (CAst.make ?loc:x.loc id,scopes))
@@ -1611,47 +1643,49 @@ let drop_notations_pattern looked_for genv =
end
| _ -> CErrors.anomaly Pp.(str "Invalid return pattern from Notation.interp_prim_token_cases_pattern_expr."))) x
in
- let rec drop_syndef top scopes qid pats =
+ let rec drop_syndef test_kind ?loc scopes qid pats =
try
+ if qualid_is_ident qid && Option.cata (Id.Set.mem (qualid_basename qid)) false env.pat_ids then
+ raise Not_found;
match Nametab.locate_extended qid with
| SynDef sp ->
let filter (vars,a) =
try match a with
| NRef g ->
(* Convention: do not deactivate implicit arguments and scopes for further arguments *)
- test_kind top g;
+ test_kind ?loc g;
let () = assert (List.is_empty vars) in
let (_,argscs) = find_remaining_scopes [] pats g in
Some (g, [], List.map2 (in_pat_sc scopes) argscs pats)
| NApp (NRef g,[]) -> (* special case: Syndef for @Cstr deactivates implicit arguments *)
- test_kind top g;
+ test_kind ?loc g;
let () = assert (List.is_empty vars) in
let (_,argscs) = find_remaining_scopes [] pats g in
Some (g, List.map2 (in_pat_sc scopes) argscs pats, [])
| NApp (NRef g,args) ->
(* Convention: do not deactivate implicit arguments and scopes for further arguments *)
- test_kind top g;
+ test_kind ?loc g;
let nvars = List.length vars in
if List.length pats < nvars then error_not_enough_arguments ?loc:qid.loc;
let pats1,pats2 = List.chop nvars pats in
let subst = split_by_type_pat vars (pats1,[]) in
- let idspl1 = List.map (in_not false qid.loc scopes subst []) args in
+ let idspl1 = List.map (in_not test_kind_inner qid.loc scopes subst []) args in
let (_,argscs) = find_remaining_scopes pats1 pats2 g in
Some (g, idspl1, List.map2 (in_pat_sc scopes) argscs pats2)
| _ -> raise Not_found
with Not_found -> None in
Syntax_def.search_filtered_syntactic_definition filter sp
| TrueGlobal g ->
- test_kind top g;
+ test_kind ?loc g;
Dumpglob.add_glob ?loc:qid.loc g;
let (_,argscs) = find_remaining_scopes [] pats g in
Some (g,[],List.map2 (in_pat_sc scopes) argscs pats)
with Not_found -> None
- and in_pat top scopes pt =
+ and in_pat test_kind scopes pt =
let open CAst in
let loc = pt.loc in
match pt.v with
- | CPatAlias (p, id) -> DAst.make ?loc @@ RCPatAlias (in_pat top scopes p, id)
+ | CPatAlias (p, id) -> DAst.make ?loc @@ RCPatAlias (in_pat test_kind scopes p, id)
| CPatRecord l ->
let sorted_fields =
sort_fields ~complete:false loc l (fun _idx fieldname constructor -> CAst.make ?loc @@ CPatAtom None) in
@@ -1668,7 +1702,7 @@ let drop_notations_pattern looked_for genv =
end
| CPatCstr (head, None, pl) ->
begin
- match drop_syndef top scopes head pl with
+ match drop_syndef test_kind ?loc scopes head pl with
| Some (a,b,c) -> DAst.make ?loc @@ RCPatCstr(a, b, c)
| None -> Loc.raise ?loc (InternalizationError (NotAConstructor head))
end
@@ -1682,37 +1716,37 @@ let drop_notations_pattern looked_for genv =
in
if expl_pl == [] then
(* Convention: (@r) deactivates all further implicit arguments and scopes *)
- DAst.make ?loc @@ RCPatCstr (g, List.map (in_pat false scopes) pl, [])
+ DAst.make ?loc @@ RCPatCstr (g, List.map (in_pat test_kind_inner scopes) pl, [])
else
(* Convention: (@r expl_pl) deactivates implicit arguments in expl_pl and in pl *)
(* but not scopes in expl_pl *)
let (argscs1,_) = find_remaining_scopes expl_pl pl g in
- DAst.make ?loc @@ RCPatCstr (g, List.map2 (in_pat_sc scopes) argscs1 expl_pl @ List.map (in_pat false scopes) pl, [])
+ DAst.make ?loc @@ RCPatCstr (g, List.map2 (in_pat_sc scopes) argscs1 expl_pl @ List.map (in_pat test_kind_inner scopes) pl, [])
| CPatNotation (_,(InConstrEntry,"- _"),([a],[]),[]) when is_non_zero_pat a ->
- let p = match a.CAst.v with CPatPrim (Numeral (_, p)) -> p | _ -> assert false in
- let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc (ensure_kind false loc) (Numeral (SMinus,p)) scopes in
+ let p = match a.CAst.v with CPatPrim (Number (_, p)) -> p | _ -> assert false in
+ let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc (ensure_kind test_kind_inner) (Number (SMinus,p)) scopes in
rcp_of_glob scopes pat
| CPatNotation (_,(InConstrEntry,"( _ )"),([a],[]),[]) ->
- in_pat top scopes a
+ in_pat test_kind scopes a
| CPatNotation (_,ntn,fullargs,extrargs) ->
let ntn,(terms,termlists) = contract_curly_brackets_pat ntn fullargs in
let ((ids',c),df) = Notation.interp_notation ?loc ntn scopes in
- let (terms,termlists) = split_by_type_pat ?loc ids' (terms,termlists) in
+ let subst = split_by_type_pat ?loc ids' (terms,termlists) in
Dumpglob.dump_notation_location (patntn_loc ?loc fullargs ntn) ntn df;
- in_not top loc scopes (terms,termlists) extrargs c
+ in_not test_kind loc scopes subst extrargs c
| CPatDelimiters (key, e) ->
- in_pat top (None,find_delimiters_scope ?loc key::snd scopes) e
+ in_pat test_kind (None,find_delimiters_scope ?loc key::snd scopes) e
| CPatPrim p ->
- let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc (test_kind false) p scopes in
+ let pat, _df = Notation.interp_prim_token_cases_pattern_expr ?loc test_kind_inner p scopes in
rcp_of_glob scopes pat
| CPatAtom (Some id) ->
begin
- match drop_syndef top scopes id [] with
+ match drop_syndef test_kind ?loc scopes id [] with
| Some (a,b,c) -> DAst.make ?loc @@ RCPatCstr (a, b, c)
| None -> DAst.make ?loc @@ RCPatAtom (Some ((make ?loc @@ find_pattern_variable id),scopes))
end
| CPatAtom None -> DAst.make ?loc @@ RCPatAtom None
- | CPatOr pl -> DAst.make ?loc @@ RCPatOr (List.map (in_pat top scopes) pl)
+ | CPatOr pl -> DAst.make ?loc @@ RCPatOr (List.map (in_pat test_kind scopes) pl)
| CPatCast (_,_) ->
(* We raise an error if the pattern contains a cast, due to
current restrictions on casts in patterns. Cast in patterns
@@ -1725,8 +1759,8 @@ let drop_notations_pattern looked_for genv =
This check is here and not in the parser because it would require
duplicating the levels of the [pattern] rule. *)
CErrors.user_err ?loc (Pp.strbrk "Casts are not supported in this pattern.")
- and in_pat_sc scopes x = in_pat false (x,snd scopes)
- and in_not top loc scopes (subst,substlist as fullsubst) args = function
+ and in_pat_sc scopes x = in_pat test_kind_inner (x,snd scopes)
+ and in_not (test_kind:?loc:Loc.t->'a->'b) loc scopes (subst,substlist as fullsubst) args = function
| NVar id ->
let () = assert (List.is_empty args) in
begin
@@ -1734,21 +1768,21 @@ let drop_notations_pattern looked_for genv =
(* of the notations *)
try
let (a,(scopt,subscopes)) = Id.Map.find id subst in
- in_pat top (scopt,subscopes@snd scopes) a
+ in_pat test_kind (scopt,subscopes@snd scopes) a
with Not_found ->
if Id.equal id ldots_var then DAst.make ?loc @@ RCPatAtom (Some ((make ?loc id),scopes)) else
anomaly (str "Unbound pattern notation variable: " ++ Id.print id ++ str ".")
end
| NRef g ->
- ensure_kind top loc g;
+ ensure_kind test_kind ?loc g;
let (_,argscs) = find_remaining_scopes [] args g in
DAst.make ?loc @@ RCPatCstr (g, [], List.map2 (in_pat_sc scopes) argscs args)
| NApp (NRef g,pl) ->
- ensure_kind top loc g;
+ ensure_kind test_kind ?loc g;
let (argscs1,argscs2) = find_remaining_scopes pl args g in
- let pl = List.map2 (fun x -> in_not false loc (x,snd scopes) fullsubst []) argscs1 pl in
+ let pl = List.map2 (fun x -> in_not test_kind_inner loc (x,snd scopes) fullsubst []) argscs1 pl in
let pl = add_local_defs_and_check_length loc genv g pl args in
- let args = List.map2 (fun x -> in_pat false (x,snd scopes)) argscs2 args in
+ let args = List.map2 (fun x -> in_pat test_kind_inner (x,snd scopes)) argscs2 args in
let pat =
if List.length pl = 0 then
(* Convention: if notation is @f, encoded as NApp(Nref g,[]), then
@@ -1763,10 +1797,10 @@ let drop_notations_pattern looked_for genv =
(try
(* All elements of the list are in scopes (scopt,subscopes) *)
let (l,(scopt,subscopes)) = Id.Map.find x substlist in
- let termin = in_not top loc scopes fullsubst [] terminator in
+ let termin = in_not test_kind_inner loc scopes fullsubst [] terminator in
List.fold_right (fun a t ->
let nsubst = Id.Map.add y (a, (scopt, subscopes)) subst in
- let u = in_not false loc scopes (nsubst, substlist) [] iter in
+ let u = in_not test_kind_inner loc scopes (nsubst, substlist) [] iter in
subst_pat_iterator ldots_var t u)
(if revert then List.rev l else l) termin
with Not_found ->
@@ -1775,7 +1809,7 @@ let drop_notations_pattern looked_for genv =
let () = assert (List.is_empty args) in
DAst.make ?loc @@ RCPatAtom None
| t -> error_invalid_pattern_notation ?loc ()
- in in_pat true
+ in in_pat test_kind_top env.pat_scopes pat
let rec intern_pat genv ntnvars aliases pat =
let intern_cstr_with_all_args loc c with_letin idslpl1 pl2 =
@@ -1816,19 +1850,30 @@ let rec intern_pat genv ntnvars aliases pat =
check_or_pat_variables loc ids (List.tl idsl);
(ids,List.flatten pl')
-let intern_cases_pattern genv ntnvars scopes aliases pat =
+let intern_cases_pattern test_kind genv ntnvars env aliases pat =
intern_pat genv ntnvars aliases
- (drop_notations_pattern (function GlobRef.ConstructRef _ -> () | _ -> raise Not_found) genv scopes pat)
+ (drop_notations_pattern (test_kind,test_kind) genv env pat)
let _ =
intern_cases_pattern_fwd :=
- fun ntnvars scopes p -> intern_cases_pattern (Global.env ()) ntnvars scopes empty_alias p
-
-let intern_ind_pattern genv ntnvars scopes pat =
+ fun test_kind ntnvars env p ->
+ intern_cases_pattern test_kind (Global.env ()) ntnvars env empty_alias p
+
+let intern_ind_pattern genv ntnvars env pat =
+ let test_kind_top ?loc = function
+ | GlobRef.IndRef _ -> ()
+ | GlobRef.ConstructRef _ | GlobRef.ConstRef _ | GlobRef.VarRef _ ->
+ (* A non-inductive global reference at top is an error *)
+ error_invalid_pattern_notation ?loc () in
+ let test_kind_inner ?loc = function
+ | GlobRef.ConstructRef _ -> ()
+ | GlobRef.IndRef _ | GlobRef.ConstRef _ | GlobRef.VarRef _ ->
+ (* A non-constructor global reference deep in a pattern is seen as a variable *)
+ raise Not_found in
let no_not =
try
- drop_notations_pattern (function (GlobRef.IndRef _ | GlobRef.ConstructRef _) -> () | _ -> raise Not_found) genv scopes pat
- with InternalizationError(NotAConstructor _) as exn ->
+ drop_notations_pattern (test_kind_top,test_kind_inner) genv env pat
+ with InternalizationError (NotAConstructor _) as exn ->
let _, info = Exninfo.capture exn in
error_bad_inductive_type ~info ()
in
@@ -2006,8 +2051,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
GLetIn (na.CAst.v, inc1, int,
intern_restart_binders (push_name_env ntnvars (impls_term_list 1 inc1) env na) c2)
| CNotation (_,(InConstrEntry,"- _"), ([a],[],[],[])) when is_non_zero a ->
- let p = match a.CAst.v with CPrim (Numeral (_, p)) -> p | _ -> assert false in
- intern env (CAst.make ?loc @@ CPrim (Numeral (SMinus,p)))
+ let p = match a.CAst.v with CPrim (Number (_, p)) -> p | _ -> assert false in
+ intern env (CAst.make ?loc @@ CPrim (Number (SMinus,p)))
| CNotation (_,(InConstrEntry,"( _ )"),([a],[],[],[])) -> intern env a
| CNotation (_,ntn,args) ->
let c = intern_notation intern env ntnvars loc ntn args in
@@ -2221,7 +2266,8 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
(* Expands a multiple pattern into a disjunction of multiple patterns *)
and intern_multiple_pattern env n pl =
- let idsl_pll = List.map (intern_cases_pattern globalenv ntnvars (None,env.scopes) empty_alias) pl in
+ let env = { pat_ids = None; pat_scopes = (None,env.scopes) } in
+ let idsl_pll = List.map (intern_cases_pattern test_kind_tolerant globalenv ntnvars env empty_alias) pl in
let loc = loc_of_multiple_pattern pl in
check_number_of_pattern loc n pl;
product_of_cases_patterns empty_alias idsl_pll
@@ -2262,7 +2308,7 @@ let internalize globalenv env pattern_mode (_, ntnvars as lvar) c =
let match_td,typ = match t with
| Some t ->
let with_letin,(ind,ind_ids,alias_subst,l) =
- intern_ind_pattern globalenv ntnvars (None,env.scopes) t in
+ intern_ind_pattern globalenv ntnvars (env_for_pattern (set_type_scope env)) t in
let (mib,mip) = Inductive.lookup_mind_specif globalenv ind in
let nparams = (List.length (mib.Declarations.mind_params_ctxt)) in
(* for "in Vect n", we answer (["n","n"],[(loc,"n")])
@@ -2403,7 +2449,8 @@ let intern_gen kind env sigma
let intern_constr env sigma c = intern_gen WithoutTypeConstraint env sigma c
let intern_type env sigma c = intern_gen IsType env sigma c
let intern_pattern globalenv patt =
- intern_cases_pattern globalenv Id.Map.empty (None,[]) empty_alias patt
+ let env = {pat_ids = None; pat_scopes = (None, [])} in
+ intern_cases_pattern test_kind_tolerant globalenv Id.Map.empty env empty_alias patt
(*********************************************************************)
(* Functions to parse and interpret constructions *)
@@ -2471,6 +2518,14 @@ let intern_constr_pattern env sigma ?(as_type=false) ?(ltacvars=empty_ltac_sign)
~pattern_mode:true ~ltacvars env sigma c in
pattern_of_glob_constr c
+let interp_constr_pattern env sigma ?(expected_type=WithoutTypeConstraint) c =
+ let c = intern_gen expected_type ~pattern_mode:true env sigma c in
+ let flags = { Pretyping.no_classes_no_fail_inference_flags with expand_evars = false } in
+ let sigma, c = understand_tcc ~flags env sigma ~expected_type c in
+ (* FIXME: it is necessary to be unsafe here because of the way we handle
+ evars in the pretyper. Sometimes they get solved eagerly. *)
+ pattern_of_constr env sigma (EConstr.Unsafe.to_constr c)
+
let intern_core kind env sigma ?(pattern_mode=false) ?(ltacvars=empty_ltac_sign)
{ Genintern.intern_ids = ids; Genintern.notation_variable_status = vl } c =
let tmp_scope = scope_of_type_kind env sigma kind in
@@ -2565,3 +2620,37 @@ let interp_context_evars ?program_mode ?(impl_env=empty_internalization_env) env
let int_env,bl = intern_context env impl_env params in
let sigma, x = interp_glob_context_evars ?program_mode env sigma bl in
sigma, (int_env, x)
+
+
+(** Local universe and constraint declarations. *)
+
+let interp_univ_constraints env evd cstrs =
+ let interp (evd,cstrs) (u, d, u') =
+ let ul = Pretyping.interp_known_glob_level evd u in
+ let u'l = Pretyping.interp_known_glob_level evd u' in
+ let cstr = (ul,d,u'l) in
+ let cstrs' = Univ.Constraint.add cstr cstrs in
+ try let evd = Evd.add_constraints evd (Univ.Constraint.singleton cstr) in
+ evd, cstrs'
+ with Univ.UniverseInconsistency e as exn ->
+ let _, info = Exninfo.capture exn in
+ CErrors.user_err ~hdr:"interp_constraint" ~info
+ (Univ.explain_universe_inconsistency (Termops.pr_evd_level evd) e)
+ in
+ List.fold_left interp (evd,Univ.Constraint.empty) cstrs
+
+let interp_univ_decl env decl =
+ let open UState in
+ let binders : lident list = decl.univdecl_instance in
+ let evd = Evd.from_env ~binders env in
+ let evd, cstrs = interp_univ_constraints env evd decl.univdecl_constraints in
+ let decl = { univdecl_instance = binders;
+ univdecl_extensible_instance = decl.univdecl_extensible_instance;
+ univdecl_constraints = cstrs;
+ univdecl_extensible_constraints = decl.univdecl_extensible_constraints }
+ in evd, decl
+
+let interp_univ_decl_opt env l =
+ match l with
+ | None -> Evd.from_env env, UState.default_univ_decl
+ | Some decl -> interp_univ_decl env decl
diff --git a/interp/constrintern.mli b/interp/constrintern.mli
index 898a3e09c8..9037ed5414 100644
--- a/interp/constrintern.mli
+++ b/interp/constrintern.mli
@@ -136,10 +136,16 @@ val interp_type_evars_impls : ?flags:inference_flags -> env -> evar_map ->
(** Interprets constr patterns *)
+(** Without typing *)
val intern_constr_pattern :
env -> evar_map -> ?as_type:bool -> ?ltacvars:ltac_sign ->
constr_pattern_expr -> patvar list * constr_pattern
+(** With typing *)
+val interp_constr_pattern :
+ env -> evar_map -> ?expected_type:typing_constraint ->
+ constr_pattern_expr -> constr_pattern
+
(** Raise Not_found if syndef not bound to a name and error if unexisting ref *)
val intern_reference : qualid -> GlobRef.t
@@ -191,3 +197,10 @@ val get_asymmetric_patterns : unit -> bool
val check_duplicate : ?loc:Loc.t -> (qualid * constr_expr) list -> unit
(** Check that a list of record field definitions doesn't contain
duplicates. *)
+
+(** Local universe and constraint declarations. *)
+val interp_univ_decl : Environ.env -> universe_decl_expr ->
+ Evd.evar_map * UState.universe_decl
+
+val interp_univ_decl_opt : Environ.env -> universe_decl_expr option ->
+ Evd.evar_map * UState.universe_decl
diff --git a/interp/dumpglob.ml b/interp/dumpglob.ml
index d57c05788d..3ec92cf691 100644
--- a/interp/dumpglob.ml
+++ b/interp/dumpglob.ml
@@ -26,19 +26,29 @@ type glob_output =
| MultFiles
| File of string
-let glob_output = ref NoGlob
+let glob_output = ref []
-let dump () = !glob_output <> NoGlob
+let get_output () = match !glob_output with
+ | [] -> NoGlob
+ | g::_ -> g
-let set_glob_output mode =
- glob_output := mode
+let push_output g = glob_output := g::!glob_output
+
+let pop_output () = glob_output := match !glob_output with
+ | [] -> CErrors.anomaly (Pp.str "No output left to pop")
+ | _::ds -> ds
+
+let pause () = push_output NoGlob
+let continue = pop_output
+
+let dump () = get_output () <> NoGlob
let dump_string s =
- if dump () && !glob_output != Feedback then
+ if dump () && get_output () != Feedback then
output_string !glob_file s
let start_dump_glob ~vfile ~vofile =
- match !glob_output with
+ match get_output () with
| MultFiles ->
open_glob_file (Filename.chop_extension vofile ^ ".glob");
output_string !glob_file "DIGEST ";
@@ -51,14 +61,10 @@ let start_dump_glob ~vfile ~vofile =
()
let end_dump_glob () =
- match !glob_output with
+ match get_output () with
| MultFiles | File _ -> close_glob_file ()
| NoGlob | Feedback -> ()
-let previous_state = ref MultFiles
-let pause () = previous_state := !glob_output; glob_output := NoGlob
-let continue () = glob_output := !previous_state
-
open Decls
open Declarations
@@ -141,7 +147,7 @@ let interval loc =
loc1, loc2-1
let dump_ref ?loc filepath modpath ident ty =
- match !glob_output with
+ match get_output () with
| Feedback ->
Option.iter (fun loc ->
Feedback.feedback (Feedback.GlobRef (loc, filepath, modpath, ident, ty))
@@ -247,7 +253,7 @@ let add_glob_kn ?loc kn =
add_glob_gen ?loc sp lib_dp "syndef"
let dump_def ?loc ty secpath id = Option.iter (fun loc ->
- if !glob_output = Feedback then
+ if get_output () = Feedback then
Feedback.feedback (Feedback.GlobDef (loc, id, secpath, ty))
else
let bl,el = interval loc in
diff --git a/interp/dumpglob.mli b/interp/dumpglob.mli
index be1e3f05d2..857991cb3f 100644
--- a/interp/dumpglob.mli
+++ b/interp/dumpglob.mli
@@ -19,11 +19,19 @@ type glob_output =
| MultFiles (* one glob file per .v file *)
| File of string (* Single file for all coqc arguments *)
-(* Default "NoGlob" *)
-val set_glob_output : glob_output -> unit
+(** [push_output o] temporarily overrides the output location to [o].
+ The original output can be restored using [pop_output] *)
+val push_output : glob_output -> unit
+(** Restores the original output that was overridden by [push_output] *)
+val pop_output : unit -> unit
+
+(** Alias for [push_output NoGlob] *)
val pause : unit -> unit
+
+(** Deprecated alias for [pop_output] *)
val continue : unit -> unit
+[@@ocaml.deprecated "Use pop_output"]
val add_glob : ?loc:Loc.t -> Names.GlobRef.t -> unit
val add_glob_kn : ?loc:Loc.t -> Names.KerName.t -> unit
diff --git a/interp/implicit_quantifiers.ml b/interp/implicit_quantifiers.ml
index 2853eef5c5..ee07fb6ed1 100644
--- a/interp/implicit_quantifiers.ml
+++ b/interp/implicit_quantifiers.ml
@@ -114,8 +114,8 @@ let generalizable_vars_of_glob_constr ?(bound=Id.Set.empty) ?(allowed=Id.Set.emp
ungeneralizable loc id) vars;
vars
-let rec make_fresh ids env x =
- if is_freevar ids env x then x else make_fresh ids env (Nameops.increment_subscript x)
+let make_fresh ids env x =
+ Namegen.next_ident_away_from x (fun x -> not (is_freevar ids env x))
let next_name_away_from na avoid =
match na with
diff --git a/interp/modintern.ml b/interp/modintern.ml
index 50f90ebea7..5f17d3e284 100644
--- a/interp/modintern.ml
+++ b/interp/modintern.ml
@@ -106,7 +106,7 @@ let transl_with_decl env base kind = function
| CWith_Module ({CAst.v=fqid},qid) ->
WithMod (fqid,lookup_module qid), Univ.ContextSet.empty
| CWith_Definition ({CAst.v=fqid},udecl,c) ->
- let sigma, udecl = Constrexpr_ops.interp_univ_decl_opt env udecl in
+ let sigma, udecl = interp_univ_decl_opt env udecl in
let c, ectx = interp_constr env sigma c in
let poly = lookup_polymorphism env base kind fqid in
begin match UState.check_univ_decl ~poly ectx udecl with
diff --git a/interp/notation.ml b/interp/notation.ml
index 269e20c16e..8d05fab63c 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -32,7 +32,7 @@ open NumTok
fail if a number has no interpretation in the scope (e.g. there is
no interpretation for negative numbers in [nat]); interpreters both for
terms and patterns can be set; these interpreters are in permanent table
- [numeral_interpreter_tab]
+ [number_interpreter_tab]
- a set of ML printers for expressions denoting numbers parsable in
this scope
- a set of interpretations for infix (more generally distfix) notations
@@ -341,22 +341,27 @@ type notation_rule = interp_rule * interpretation * notation_applicative_status
let notation_rule_eq (rule1,pat1,s1 as x1) (rule2,pat2,s2 as x2) =
x1 == x2 || (rule1 = rule2 && interpretation_eq pat1 pat2 && s1 = s2)
+let also_cases_notation_rule_eq (also_cases1,rule1) (also_cases2,rule2) =
+ (* No need in principle to compare also_cases as it is inferred *)
+ also_cases1 = also_cases2 && notation_rule_eq rule1 rule2
+
let keymap_add key interp map =
let old = try KeyMap.find key map with Not_found -> [] in
(* In case of re-import, no need to keep the previous copy *)
- let old = try List.remove_first (notation_rule_eq interp) old with Not_found -> old in
+ let old = try List.remove_first (also_cases_notation_rule_eq interp) old with Not_found -> old in
KeyMap.add key (interp :: old) map
let keymap_remove key interp map =
let old = try KeyMap.find key map with Not_found -> [] in
- KeyMap.add key (List.remove_first (notation_rule_eq interp) old) map
+ KeyMap.add key (List.remove_first (also_cases_notation_rule_eq interp) old) map
let keymap_find key map =
try KeyMap.find key map
with Not_found -> []
(* Scopes table : interpretation -> scope_name *)
-let notations_key_table = ref (KeyMap.empty : notation_rule list KeyMap.t)
+(* Boolean = for cases pattern also *)
+let notations_key_table = ref (KeyMap.empty : (bool * notation_rule) list KeyMap.t)
let glob_prim_constr_key c = match DAst.get c with
| GRef (ref, _) -> Some (canonical_gr ref)
@@ -446,13 +451,13 @@ module InnerPrimToken = struct
let do_interp ?loc interp primtok =
match primtok, interp with
- | Numeral n, RawNumInterp interp -> interp ?loc n
- | Numeral n, BigNumInterp interp ->
+ | Number n, RawNumInterp interp -> interp ?loc n
+ | Number 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 _),
+ | (Number _ | String _),
(RawNumInterp _ | BigNumInterp _ | StringInterp _) -> raise Not_found
type uninterpreter =
@@ -466,16 +471,16 @@ module InnerPrimToken = struct
| StringUninterp f, StringUninterp f' -> f == f'
| _ -> false
- let mkNumeral n =
- Numeral (NumTok.Signed.of_bigint CDec n)
+ let mkNumber n =
+ Number (NumTok.Signed.of_bigint CDec n)
let mkString = function
| None -> None
| Some s -> if Unicode.is_utf8 s then Some (String s) else None
let do_uninterp uninterp g = match uninterp with
- | RawNumUninterp u -> Option.map (fun (s,n) -> Numeral (s,n)) (u g)
- | BigNumUninterp u -> Option.map mkNumeral (u g)
+ | RawNumUninterp u -> Option.map (fun (s,n) -> Number (s,n)) (u g)
+ | BigNumUninterp u -> Option.map mkNumber (u g)
| StringUninterp u -> mkString (u g)
end
@@ -495,7 +500,7 @@ let prim_token_uninterpreters =
(Hashtbl.create 7 : (prim_token_uid, InnerPrimToken.uninterpreter) Hashtbl.t)
(*******************************************************)
-(* Numeral notation interpretation *)
+(* Number notation interpretation *)
type prim_token_notation_error =
| UnexpectedTerm of Constr.t
| UnexpectedNonOptionTerm of Constr.t
@@ -519,21 +524,21 @@ type z_pos_ty =
{ z_ty : Names.inductive;
pos_ty : Names.inductive }
-type numeral_ty =
+type number_ty =
{ int : int_ty;
decimal : Names.inductive;
hexadecimal : Names.inductive;
- numeral : Names.inductive }
+ number : Names.inductive }
type target_kind =
- | Int of int_ty (* Coq.Init.Numeral.int + uint *)
- | UInt of int_ty (* Coq.Init.Numeral.uint *)
+ | Int of int_ty (* Coq.Init.Number.int + uint *)
+ | UInt of int_ty (* Coq.Init.Number.uint *)
| Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *)
| Int63 (* Coq.Numbers.Cyclic.Int63.Int63.int *)
- | Numeral of numeral_ty (* Coq.Init.Numeral.numeral + uint + int *)
+ | Number of number_ty (* Coq.Init.Number.number + uint + int *)
| DecimalInt of int_ty (* Coq.Init.Decimal.int + uint (deprecated) *)
| DecimalUInt of int_ty (* Coq.Init.Decimal.uint (deprecated) *)
- | Decimal of numeral_ty (* Coq.Init.Decimal.Decimal + uint + int (deprecated) *)
+ | Decimal of number_ty (* Coq.Init.Decimal.Decimal + uint + int (deprecated) *)
type string_target_kind =
| ListByte
@@ -542,19 +547,36 @@ type string_target_kind =
type option_kind = Option | Direct
type 'target conversion_kind = 'target * option_kind
+(** A postprocessing translation [to_post] can be done after execution
+ of the [to_ty] interpreter. The reverse translation is performed
+ before the [of_ty] uninterpreter.
+
+ [to_post] is an array of [n] lists [l_i] of tuples [(f, t,
+ args)]. When the head symbol of the translated term matches one of
+ the [f] in the list [l_0] it is replaced by [t] and its arguments
+ are translated acording to [args] where [ToPostCopy] means that the
+ argument is kept unchanged and [ToPostAs k] means that the
+ argument is recursively translated according to [l_k].
+ [ToPostHole] introduces an additional implicit argument hole
+ (in the reverse translation, the corresponding argument is removed).
+ [ToPostCheck r] behaves as [ToPostCopy] except in the reverse
+ translation which fails if the copied term is not [r].
+ When [n] is null, no translation is performed. *)
+type to_post_arg = ToPostCopy | ToPostAs of int | ToPostHole | ToPostCheck of GlobRef.t
type ('target, 'warning) prim_token_notation_obj =
{ to_kind : 'target conversion_kind;
to_ty : GlobRef.t;
+ to_post : ((GlobRef.t * GlobRef.t * to_post_arg list) list) array;
of_kind : 'target conversion_kind;
of_ty : GlobRef.t;
ty_name : Libnames.qualid; (* for warnings / error messages *)
warning : 'warning }
-type numeral_notation_obj = (target_kind, numnot_option) prim_token_notation_obj
+type number_notation_obj = (target_kind, numnot_option) prim_token_notation_obj
type string_notation_obj = (string_target_kind, unit) prim_token_notation_obj
module PrimTokenNotation = struct
-(** * Code shared between Numeral notation and String notation *)
+(** * Code shared between Number notation and String notation *)
(** Reduction
The constr [c] below isn't necessarily well-typed, since we
@@ -588,22 +610,69 @@ exception NotAValidPrimToken
to [constr] for the subset that concerns us.
Note that if you update [constr_of_glob], you should update the
- corresponding numeral notation *and* string notation doc in
+ corresponding number notation *and* string notation doc in
doc/sphinx/user-extensions/syntax-extensions.rst that describes
what it means for a term to be ground / to be able to be
considered for parsing. *)
-let rec constr_of_glob env sigma g = match DAst.get g with
- | Glob_term.GRef (GlobRef.ConstructRef c, _) ->
- let sigma,c = Evd.fresh_constructor_instance env sigma c in
- sigma,mkConstructU c
- | Glob_term.GRef (GlobRef.IndRef c, _) ->
- let sigma,c = Evd.fresh_inductive_instance env sigma c in
- sigma,mkIndU c
+let constr_of_globref allow_constant env sigma = function
+ | GlobRef.ConstructRef c ->
+ let sigma,c = Evd.fresh_constructor_instance env sigma c in
+ sigma,mkConstructU c
+ | GlobRef.IndRef c ->
+ let sigma,c = Evd.fresh_inductive_instance env sigma c in
+ sigma,mkIndU c
+ | GlobRef.ConstRef c when allow_constant ->
+ let sigma,c = Evd.fresh_constant_instance env sigma c in
+ sigma,mkConstU c
+ | _ -> raise NotAValidPrimToken
+
+let rec constr_of_glob allow_constant to_post post env sigma g = match DAst.get g with
+ | Glob_term.GRef (r, _) ->
+ let o = List.find_opt (fun (_,r',_) -> GlobRef.equal r r') post in
+ begin match o with
+ | None -> constr_of_globref allow_constant env sigma r
+ | Some (r, _, a) ->
+ (* [g] is not a GApp so check that [post]
+ does not expect any actual argument
+ (i.e., [a] contains only ToPostHole since they mean "ignore arg") *)
+ if List.exists ((<>) ToPostHole) a then raise NotAValidPrimToken;
+ constr_of_globref true env sigma r
+ end
| Glob_term.GApp (gc, gcl) ->
- let sigma,c = constr_of_glob env sigma gc in
- let sigma,cl = List.fold_left_map (constr_of_glob env) sigma gcl in
- sigma,mkApp (c, Array.of_list cl)
+ let o = match DAst.get gc with
+ | Glob_term.GRef (r, _) -> List.find_opt (fun (_,r',_) -> GlobRef.equal r r') post
+ | _ -> None in
+ begin match o with
+ | None ->
+ let sigma,c = constr_of_glob allow_constant to_post post env sigma gc in
+ let sigma,cl = List.fold_left_map (constr_of_glob allow_constant to_post post env) sigma gcl in
+ sigma,mkApp (c, Array.of_list cl)
+ | Some (r, _, a) ->
+ let sigma,c = constr_of_globref true env sigma r in
+ let rec aux sigma a gcl = match a, gcl with
+ | [], [] -> sigma,[]
+ | ToPostCopy :: a, gc :: gcl ->
+ let sigma,c = constr_of_glob allow_constant [||] [] env sigma gc in
+ let sigma,cl = aux sigma a gcl in
+ sigma, c :: cl
+ | ToPostCheck r :: a, gc :: gcl ->
+ let () = match DAst.get gc with
+ | Glob_term.GRef (r', _) when GlobRef.equal r r' -> ()
+ | _ -> raise NotAValidPrimToken in
+ let sigma,c = constr_of_glob true [||] [] env sigma gc in
+ let sigma,cl = aux sigma a gcl in
+ sigma, c :: cl
+ | ToPostAs i :: a, gc :: gcl ->
+ let sigma,c = constr_of_glob allow_constant to_post to_post.(i) env sigma gc in
+ let sigma,cl = aux sigma a gcl in
+ sigma, c :: cl
+ | ToPostHole :: post, _ :: gcl -> aux sigma post gcl
+ | [], _ :: _ | _ :: _, [] -> raise NotAValidPrimToken
+ in
+ let sigma,cl = aux sigma a gcl in
+ sigma,mkApp (c, Array.of_list cl)
+ end
| Glob_term.GInt i -> sigma, mkInt i
| Glob_term.GSort gs ->
let sigma,c = Evd.fresh_sort_in_family sigma (Glob_ops.glob_sort_family gs) in
@@ -611,6 +680,10 @@ let rec constr_of_glob env sigma g = match DAst.get g with
| _ ->
raise NotAValidPrimToken
+let constr_of_glob to_post env sigma (Glob_term.AnyGlobConstr g) =
+ let post = match to_post with [||] -> [] | _ -> to_post.(0) in
+ constr_of_glob false to_post post env sigma g
+
let rec glob_of_constr token_kind ?loc env sigma c = match Constr.kind c with
| App (c, ca) ->
let c = glob_of_constr token_kind ?loc env sigma c in
@@ -632,9 +705,38 @@ let no_such_prim_token uninterpreted_token_kind ?loc ty =
(str ("Cannot interpret this "^uninterpreted_token_kind^" as a value of type ") ++
pr_qualid ty)
-let interp_option uninterpreted_token_kind token_kind ty ?loc env sigma c =
+let rec postprocess token_kind ?loc ty to_post post g =
+ let g', gl = match DAst.get g with Glob_term.GApp (g, gl) -> g, gl | _ -> g, [] in
+ let o =
+ match DAst.get g' with
+ | Glob_term.GRef (r, None) ->
+ List.find_opt (fun (r',_,_) -> GlobRef.equal r r') post
+ | _ -> None in
+ match o with None -> g | Some (_, r, a) ->
+ let rec f n a gl = match a, gl with
+ | [], [] -> []
+ | ToPostHole :: a, gl ->
+ let e = Evar_kinds.ImplicitArg (r, (n, None), true) in
+ let h = DAst.make ?loc (Glob_term.GHole (e, Namegen.IntroAnonymous, None)) in
+ h :: f (n+1) a gl
+ | (ToPostCopy | ToPostCheck _) :: a, g :: gl -> g :: f (n+1) a gl
+ | ToPostAs c :: a, g :: gl ->
+ postprocess token_kind ?loc ty to_post to_post.(c) g :: f (n+1) a gl
+ | [], _::_ | _::_, [] ->
+ no_such_prim_token token_kind ?loc ty
+ in
+ let gl = f 1 a gl in
+ let g = DAst.make ?loc (Glob_term.GRef (r, None)) in
+ DAst.make ?loc (Glob_term.GApp (g, gl))
+
+let glob_of_constr token_kind ty ?loc env sigma to_post c =
+ let g = glob_of_constr token_kind ?loc env sigma c in
+ match to_post with [||] -> g | _ ->
+ postprocess token_kind ?loc ty to_post to_post.(0) g
+
+let interp_option uninterpreted_token_kind token_kind ty ?loc env sigma to_post c =
match Constr.kind c with
- | App (_Some, [| _; c |]) -> glob_of_constr token_kind ?loc env sigma c
+ | App (_Some, [| _; c |]) -> glob_of_constr token_kind ty ?loc env sigma to_post c
| App (_None, [| _ |]) -> no_such_prim_token uninterpreted_token_kind ?loc ty
| x -> Loc.raise ?loc (PrimTokenNotationError(token_kind,env,sigma,UnexpectedNonOptionTerm c))
@@ -643,13 +745,13 @@ let uninterp_option c =
| App (_Some, [| _; x |]) -> x
| _ -> raise NotAValidPrimToken
-let uninterp to_raw o (Glob_term.AnyGlobConstr n) =
+let uninterp to_raw o n =
let env = Global.env () in
let sigma = Evd.from_env env in
let sigma,of_ty = Evd.fresh_global env sigma o.of_ty in
let of_ty = EConstr.Unsafe.to_constr of_ty in
try
- let sigma,n = constr_of_glob env sigma n in
+ let sigma,n = constr_of_glob o.to_post env sigma n in
let c = eval_constr_app env sigma of_ty n in
let c = if snd o.of_kind == Direct then c else uninterp_option c in
Some (to_raw (fst o.of_kind, c))
@@ -670,8 +772,8 @@ let rec int63_of_pos_bigint i =
(Uint63.mul (Uint63.of_int 2) (int63_of_pos_bigint quo))
else Uint63.mul (Uint63.of_int 2) (int63_of_pos_bigint quo)
-module Numeral = struct
-(** * Numeral notation *)
+module Numbers = struct
+(** * Number notation *)
open PrimTokenNotation
let warn_large_num =
@@ -727,7 +829,7 @@ let coqint_of_rawnum inds c (sign,n) =
let pos_neg = match sign with SPlus -> 1 | SMinus -> 2 in
mkApp (mkConstruct (ind, pos_neg), [|uint|])
-let coqnumeral_of_rawnum inds c n =
+let coqnumber_of_rawnum inds c n =
let ind = match c with CDec -> inds.decimal | CHex -> inds.hexadecimal in
let i, f, e = NumTok.Signed.to_int_frac_and_exponent n in
let i = coqint_of_rawnum inds.int c i in
@@ -739,19 +841,19 @@ let coqnumeral_of_rawnum inds c n =
mkApp (mkConstruct (ind, 2), [|i; f; e|]) (* (D|Hexad)ecimalExp *)
let mkDecHex ind c n = match c with
- | CDec -> mkApp (mkConstruct (ind, 1), [|n|]) (* (UInt|Int|)Dec *)
- | CHex -> mkApp (mkConstruct (ind, 2), [|n|]) (* (UInt|Int|)Hex *)
+ | CDec -> mkApp (mkConstruct (ind, 1), [|n|]) (* (UInt|Int|)Decimal *)
+ | CHex -> mkApp (mkConstruct (ind, 2), [|n|]) (* (UInt|Int|)Hexadecimal *)
exception NonDecimal
-let decimal_coqnumeral_of_rawnum inds n =
+let decimal_coqnumber_of_rawnum inds n =
if NumTok.Signed.classify n <> CDec then raise NonDecimal;
- coqnumeral_of_rawnum inds CDec n
+ coqnumber_of_rawnum inds CDec n
-let coqnumeral_of_rawnum inds n =
+let coqnumber_of_rawnum inds n =
let c = NumTok.Signed.classify n in
- let n = coqnumeral_of_rawnum inds c n in
- mkDecHex inds.numeral c n
+ let n = coqnumber_of_rawnum inds c n in
+ mkDecHex inds.number c n
let decimal_coquint_of_rawnum inds n =
if NumTok.UnsignedNat.classify n <> CDec then raise NonDecimal;
@@ -801,7 +903,7 @@ let rawnum_of_coqint cl c =
| _ -> raise NotAValidPrimToken)
| _ -> raise NotAValidPrimToken
-let rawnum_of_coqnumeral cl c =
+let rawnum_of_coqnumber cl c =
let of_ife i f e =
let n = rawnum_of_coqint cl i in
let f = try Some (rawnum_of_coquint cl f) with NotAValidPrimToken -> None in
@@ -815,17 +917,17 @@ let rawnum_of_coqnumeral cl c =
let destDecHex c = match Constr.kind c with
| App (c,[|c'|]) ->
(match Constr.kind c with
- | Construct ((_,1), _) (* (UInt|Int|)Dec *) -> CDec, c'
- | Construct ((_,2), _) (* (UInt|Int|)Hex *) -> CHex, c'
+ | Construct ((_,1), _) (* (UInt|Int|)Decimal *) -> CDec, c'
+ | Construct ((_,2), _) (* (UInt|Int|)Hexadecimal *) -> CHex, c'
| _ -> raise NotAValidPrimToken)
| _ -> raise NotAValidPrimToken
-let decimal_rawnum_of_coqnumeral c =
- rawnum_of_coqnumeral CDec c
+let decimal_rawnum_of_coqnumber c =
+ rawnum_of_coqnumber CDec c
-let rawnum_of_coqnumeral c =
+let rawnum_of_coqnumber c =
let cl, c = destDecHex c in
- rawnum_of_coqnumeral cl c
+ rawnum_of_coqnumber cl c
let decimal_rawnum_of_coquint c =
rawnum_of_coquint CDec c
@@ -947,9 +1049,9 @@ let interp o ?loc n =
interp_int63 ?loc (NumTok.SignedNat.to_bigint n)
| (Int _ | UInt _ | DecimalInt _ | DecimalUInt _ | Z _ | Int63), _ ->
no_such_prim_token "number" ?loc o.ty_name
- | Numeral numeral_ty, _ -> coqnumeral_of_rawnum numeral_ty n
- | Decimal numeral_ty, _ ->
- (try decimal_coqnumeral_of_rawnum numeral_ty n
+ | Number number_ty, _ -> coqnumber_of_rawnum number_ty n
+ | Decimal number_ty, _ ->
+ (try decimal_coqnumber_of_rawnum number_ty n
with NonDecimal -> no_such_prim_token "number" ?loc o.ty_name)
in
let env = Global.env () in
@@ -959,12 +1061,13 @@ let interp o ?loc n =
match o.warning, snd o.to_kind with
| 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|]))
+ assert (Array.length o.to_post = 0);
+ glob_of_constr "number" o.ty_name ?loc env sigma o.to_post (mkApp (to_ty,[|c|]))
| _ ->
let res = eval_constr_app env sigma to_ty c in
match snd o.to_kind with
- | Direct -> glob_of_constr "numeral" ?loc env sigma res
- | Option -> interp_option "number" "numeral" o.ty_name ?loc env sigma res
+ | Direct -> glob_of_constr "number" o.ty_name ?loc env sigma o.to_post res
+ | Option -> interp_option "number" "number" o.ty_name ?loc env sigma o.to_post res
let uninterp o n =
PrimTokenNotation.uninterp
@@ -973,10 +1076,10 @@ let uninterp o n =
| (UInt _, c) -> NumTok.Signed.of_nat (rawnum_of_coquint c)
| (Z _, c) -> NumTok.Signed.of_bigint CDec (bigint_of_z c)
| (Int63, c) -> NumTok.Signed.of_bigint CDec (bigint_of_int63 c)
- | (Numeral _, c) -> rawnum_of_coqnumeral c
+ | (Number _, c) -> rawnum_of_coqnumber c
| (DecimalInt _, c) -> NumTok.Signed.of_int (decimal_rawnum_of_coqint c)
| (DecimalUInt _, c) -> NumTok.Signed.of_nat (decimal_rawnum_of_coquint c)
- | (Decimal _, c) -> decimal_rawnum_of_coqnumeral c
+ | (Decimal _, c) -> decimal_rawnum_of_coqnumber c
end o n
end
@@ -1009,11 +1112,12 @@ let coqbyte_of_string ?loc byte s =
let p =
if Int.equal (String.length s) 1 then int_of_char s.[0]
else
- if Int.equal (String.length s) 3 && is_digit s.[0] && is_digit s.[1] && is_digit s.[2]
- then int_of_string s
- else
+ let n =
+ if Int.equal (String.length s) 3 && is_digit s.[0] && is_digit s.[1] && is_digit s.[2]
+ then int_of_string s else 256 in
+ if n < 256 then n else
user_err ?loc ~hdr:"coqbyte_of_string"
- (str "Expects a single character or a three-digits ascii code.") in
+ (str "Expects a single character or a three-digit ASCII code.") in
coqbyte_of_char_code byte p
let coqbyte_of_char byte c = coqbyte_of_char_code byte (Char.code c)
@@ -1068,8 +1172,8 @@ let interp o ?loc n =
let to_ty = EConstr.Unsafe.to_constr to_ty in
let res = eval_constr_app env sigma to_ty c in
match snd o.to_kind with
- | Direct -> glob_of_constr "string" ?loc env sigma res
- | Option -> interp_option "string" "string" o.ty_name ?loc env sigma res
+ | Direct -> glob_of_constr "string" o.ty_name ?loc env sigma o.to_post res
+ | Option -> interp_option "string" "string" o.ty_name ?loc env sigma o.to_post res
let uninterp o n =
PrimTokenNotation.uninterp
@@ -1081,21 +1185,21 @@ end
(* A [prim_token_infos], which is synchronized with the document
state, either contains a unique id pointing to an unsynchronized
- prim token function, or a numeral notation object describing how to
+ prim token function, or a number notation object describing how to
interpret and uninterpret. We provide [prim_token_infos] because
we expect plugins to provide their own interpretation functions,
- rather than going through numeral notations, which are available as
+ rather than going through number notations, which are available as
a vernacular. *)
type prim_token_interp_info =
Uid of prim_token_uid
- | NumeralNotation of numeral_notation_obj
+ | NumberNotation of number_notation_obj
| StringNotation of string_notation_obj
type prim_token_infos = {
pt_local : bool; (** Is this interpretation local? *)
pt_scope : scope_name; (** Concerned scope *)
- pt_interp_info : prim_token_interp_info; (** Unique id "pointing" to (un)interp functions, OR a numeral notation object describing (un)interp functions *)
+ pt_interp_info : prim_token_interp_info; (** Unique id "pointing" to (un)interp functions, OR a number notation object describing (un)interp functions *)
pt_required : required_module; (** Module that should be loaded first *)
pt_refs : GlobRef.t list; (** Entry points during uninterpretation *)
pt_in_match : bool (** Is this prim token legal in match patterns ? *)
@@ -1119,7 +1223,7 @@ let hashtbl_check_and_set allow_overwrite uid f h eq =
| _ ->
user_err ~hdr:"prim_token_interpreter"
(str "Unique identifier " ++ str uid ++
- str " already used to register a numeral or string (un)interpreter.")
+ str " already used to register a number or string (un)interpreter.")
let register_gen_interpretation allow_overwrite uid (interp, uninterp) =
hashtbl_check_and_set
@@ -1147,7 +1251,6 @@ let cache_prim_token_interpretation (_,infos) =
String.Map.add sc (infos.pt_required,ptii) !prim_token_interp_infos;
let add_uninterp r =
let l = try GlobRef.Map.find r !prim_token_uninterp_infos with Not_found -> [] in
- let l = List.remove_assoc_f String.equal sc l in
prim_token_uninterp_infos :=
GlobRef.Map.add r ((sc,(ptii,infos.pt_in_match)) :: l)
!prim_token_uninterp_infos in
@@ -1220,7 +1323,7 @@ let check_required_module ?loc sc (sp,d) =
(str "Cannot interpret in " ++ str sc ++ str " without requiring first module " ++
str (List.last d) ++ str ".")
-(* Look if some notation or numeral printer in [scope] can be used in
+(* Look if some notation or number printer in [scope] can be used in
the scope stack [scopes], and if yes, using delimiters or not *)
let find_with_delimiters = function
@@ -1237,7 +1340,7 @@ let rec find_without_delimiters find (ntn_scope,ntn) = function
| NotationInScope scope' when String.equal scope scope' ->
Some (None,None)
| _ ->
- (* If the most recently open scope has a notation/numeral printer
+ (* If the most recently open scope has a notation/number printer
but not the expected one then we need delimiters *)
if find scope then
find_with_delimiters ntn_scope
@@ -1333,13 +1436,13 @@ let check_printing_override (scopt,ntn) data parsingdata printingdata =
exists) printingdata in
parsing_update, exists
-let remove_uninterpretation rule (metas,c as pat) =
+let remove_uninterpretation rule also_in_cases_pattern (metas,c as pat) =
let (key,n) = notation_constr_key c in
- notations_key_table := keymap_remove key (rule,pat,n) !notations_key_table
+ notations_key_table := keymap_remove key (also_in_cases_pattern,(rule,pat,n)) !notations_key_table
-let declare_uninterpretation rule (metas,c as pat) =
+let declare_uninterpretation ?(also_in_cases_pattern=true) rule (metas,c as pat) =
let (key,n) = notation_constr_key c in
- notations_key_table := keymap_add key (rule,pat,n) !notations_key_table
+ notations_key_table := keymap_add key (also_in_cases_pattern,(rule,pat,n)) !notations_key_table
let update_notation_data (scopt,ntn) use data table =
let (parsingdata,printingdata) =
@@ -1375,8 +1478,8 @@ let find_notation ntn sc =
| _ -> raise Not_found
let notation_of_prim_token = function
- | Constrexpr.Numeral (SPlus,n) -> InConstrEntry, NumTok.Unsigned.sprint n
- | Constrexpr.Numeral (SMinus,n) -> InConstrEntry, "- "^NumTok.Unsigned.sprint n
+ | Constrexpr.Number (SPlus,n) -> InConstrEntry, NumTok.Unsigned.sprint n
+ | Constrexpr.Number (SMinus,n) -> InConstrEntry, "- "^NumTok.Unsigned.sprint n
| String _ -> raise Not_found
let find_prim_token check_allowed ?loc p sc =
@@ -1394,7 +1497,7 @@ let find_prim_token check_allowed ?loc p sc =
check_required_module ?loc sc spdir;
let interp = match info with
| Uid uid -> Hashtbl.find prim_token_interpreters uid
- | NumeralNotation o -> InnerPrimToken.RawNumInterp (Numeral.interp o)
+ | NumberNotation o -> InnerPrimToken.RawNumInterp (Numbers.interp o)
| StringNotation o -> InnerPrimToken.StringInterp (Strings.interp o)
in
let pat = InnerPrimToken.do_interp ?loc interp p in
@@ -1411,8 +1514,8 @@ let interp_prim_token_gen ?loc g p local_scopes =
let _, info = Exninfo.capture exn in
user_err ?loc ~info ~hdr:"interp_prim_token"
((match p with
- | Numeral _ ->
- str "No interpretation for numeral " ++ pr_notation (notation_of_prim_token p)
+ | Number _ ->
+ str "No interpretation for number " ++ pr_notation (notation_of_prim_token p)
| String s -> str "No interpretation for string " ++ qs s) ++ str ".")
let interp_prim_token ?loc =
@@ -1448,14 +1551,17 @@ let interp_notation ?loc ntn local_scopes =
(str "Unknown interpretation for notation " ++ pr_notation ntn ++ str ".")
let uninterp_notations c =
- List.map_append (fun key -> keymap_find key !notations_key_table)
+ List.map_append (fun key -> List.map snd (keymap_find key !notations_key_table))
(glob_constr_keys c)
+let filter_also_for_pattern =
+ List.map_filter (function (true,x) -> Some x | _ -> None)
+
let uninterp_cases_pattern_notations c =
- keymap_find (cases_pattern_key c) !notations_key_table
+ filter_also_for_pattern (keymap_find (cases_pattern_key c) !notations_key_table)
let uninterp_ind_pattern_notations ind =
- keymap_find (RefKey (canonical_gr (GlobRef.IndRef ind))) !notations_key_table
+ filter_also_for_pattern (keymap_find (RefKey (canonical_gr (GlobRef.IndRef ind))) !notations_key_table)
let has_active_parsing_rule_in_scope ntn sc =
try
@@ -1615,7 +1721,7 @@ type entry_coercion_kind =
| IsEntryGlobal of string * int
| IsEntryIdent of string * int
-let declare_notation (scopt,ntn) pat df ~use coe deprecation =
+let declare_notation (scopt,ntn) pat df ~use ~also_in_cases_pattern coe deprecation =
(* Register the interpretation *)
let scope = match scopt with NotationInScope s -> s | LastLonelyNotation -> default_scope in
let sc = find_scope scope in
@@ -1630,10 +1736,10 @@ let declare_notation (scopt,ntn) pat df ~use coe deprecation =
scope_map := String.Map.add scope sc !scope_map;
(* Update the uninterpretation cache *)
begin match printing_update with
- | Some pat -> remove_uninterpretation (NotationRule (scopt,ntn)) pat
+ | Some pat -> remove_uninterpretation (NotationRule (scopt,ntn)) also_in_cases_pattern pat
| None -> ()
end;
- if not exists && use <> OnlyParsing then declare_uninterpretation (NotationRule (scopt,ntn)) pat;
+ if not exists && use <> OnlyParsing then declare_uninterpretation ~also_in_cases_pattern (NotationRule (scopt,ntn)) pat;
(* Register visibility of lonely notations *)
if not exists then begin match scopt with
| LastLonelyNotation -> scope_stack := LonelyNotationItem ntn :: !scope_stack
@@ -1659,14 +1765,14 @@ let availability_of_prim_token n printer_scope local_scopes =
let uid = snd (String.Map.find scope !prim_token_interp_infos) in
let open InnerPrimToken in
match n, uid with
- | Constrexpr.Numeral _, NumeralNotation _ -> true
- | _, NumeralNotation _ -> false
+ | Constrexpr.Number _, NumberNotation _ -> true
+ | _, NumberNotation _ -> false
| String _, StringNotation _ -> true
| _, StringNotation _ -> false
| _, Uid uid ->
let interp = Hashtbl.find prim_token_interpreters uid in
match n, interp with
- | Constrexpr.Numeral _, (RawNumInterp _ | BigNumInterp _) -> true
+ | Constrexpr.Number _, (RawNumInterp _ | BigNumInterp _) -> true
| String _, StringInterp _ -> true
| _ -> false
with Not_found -> false
@@ -1681,7 +1787,7 @@ let rec find_uninterpretation need_delim def find = function
def
| OpenScopeItem scope :: scopes ->
(try find need_delim scope
- with Not_found -> find_uninterpretation need_delim def find scopes) (* TODO: here we should also update the need_delim list with all regular notations in scope [scope] that could shadow a numeral notation *)
+ with Not_found -> find_uninterpretation need_delim def find scopes) (* TODO: here we should also update the need_delim list with all regular notations in scope [scope] that could shadow a number notation *)
| LonelyNotationItem ntn::scopes ->
find_uninterpretation (ntn::need_delim) def find scopes
@@ -1693,7 +1799,7 @@ let uninterp_prim_token c local_scopes =
try
let uninterp = match info with
| Uid uid -> Hashtbl.find prim_token_uninterpreters uid
- | NumeralNotation o -> InnerPrimToken.RawNumUninterp (Numeral.uninterp o)
+ | NumberNotation o -> InnerPrimToken.RawNumUninterp (Numbers.uninterp o)
| StringNotation o -> InnerPrimToken.StringUninterp (Strings.uninterp o)
in
match InnerPrimToken.do_uninterp uninterp (AnyGlobConstr c) with
diff --git a/interp/notation.mli b/interp/notation.mli
index d744ff41d9..b8939ff87b 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -74,7 +74,7 @@ val find_delimiters_scope : ?loc:Loc.t -> delimiters -> scope_name
(** {6 Declare and uses back and forth an interpretation of primitive token } *)
-(** A numeral interpreter is the pair of an interpreter for **(hexa)decimal**
+(** A number interpreter is the pair of an interpreter for **(hexa)decimal**
numbers in terms and an optional interpreter in pattern, if
non integer or negative numbers are not supported, the interpreter
must fail with an appropriate error message *)
@@ -84,7 +84,7 @@ type required_module = full_path * string list
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.
+ registered interpreter/uninterpreter of number or string notation.
Using the same uid for different (un)interpreters will fail.
If at most one interpretation of prim token is used per scope,
then the scope name could be used as unique id. *)
@@ -106,7 +106,7 @@ val register_bignumeral_interpretation :
val register_string_interpretation :
?allow_overwrite:bool -> prim_token_uid -> string prim_token_interpretation -> unit
-(** * Numeral notation *)
+(** * Number notation *)
type prim_token_notation_error =
| UnexpectedTerm of Constr.t
@@ -131,21 +131,21 @@ type z_pos_ty =
{ z_ty : Names.inductive;
pos_ty : Names.inductive }
-type numeral_ty =
+type number_ty =
{ int : int_ty;
decimal : Names.inductive;
hexadecimal : Names.inductive;
- numeral : Names.inductive }
+ number : Names.inductive }
type target_kind =
- | Int of int_ty (* Coq.Init.Numeral.int + uint *)
- | UInt of int_ty (* Coq.Init.Numeral.uint *)
+ | Int of int_ty (* Coq.Init.Number.int + uint *)
+ | UInt of int_ty (* Coq.Init.Number.uint *)
| Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *)
| Int63 (* Coq.Numbers.Cyclic.Int63.Int63.int *)
- | Numeral of numeral_ty (* Coq.Init.Numeral.numeral + uint + int *)
+ | Number of number_ty (* Coq.Init.Number.number + uint + int *)
| DecimalInt of int_ty (* Coq.Init.Decimal.int + uint (deprecated) *)
| DecimalUInt of int_ty (* Coq.Init.Decimal.uint (deprecated) *)
- | Decimal of numeral_ty (* Coq.Init.Decimal.Decimal + uint + int (deprecated) *)
+ | Decimal of number_ty (* Coq.Init.Decimal.Decimal + uint + int (deprecated) *)
type string_target_kind =
| ListByte
@@ -154,26 +154,43 @@ type string_target_kind =
type option_kind = Option | Direct
type 'target conversion_kind = 'target * option_kind
+(** A postprocessing translation [to_post] can be done after execution
+ of the [to_ty] interpreter. The reverse translation is performed
+ before the [of_ty] uninterpreter.
+
+ [to_post] is an array of [n] lists [l_i] of tuples [(f, t,
+ args)]. When the head symbol of the translated term matches one of
+ the [f] in the list [l_0] it is replaced by [t] and its arguments
+ are translated acording to [args] where [ToPostCopy] means that the
+ argument is kept unchanged and [ToPostAs k] means that the
+ argument is recursively translated according to [l_k].
+ [ToPostHole] introduces an additional implicit argument hole
+ (in the reverse translation, the corresponding argument is removed).
+ [ToPostCheck r] behaves as [ToPostCopy] except in the reverse
+ translation which fails if the copied term is not [r].
+ When [n] is null, no translation is performed. *)
+type to_post_arg = ToPostCopy | ToPostAs of int | ToPostHole | ToPostCheck of GlobRef.t
type ('target, 'warning) prim_token_notation_obj =
{ to_kind : 'target conversion_kind;
to_ty : GlobRef.t;
+ to_post : ((GlobRef.t * GlobRef.t * to_post_arg list) list) array;
of_kind : 'target conversion_kind;
of_ty : GlobRef.t;
ty_name : Libnames.qualid; (* for warnings / error messages *)
warning : 'warning }
-type numeral_notation_obj = (target_kind, numnot_option) prim_token_notation_obj
+type number_notation_obj = (target_kind, numnot_option) prim_token_notation_obj
type string_notation_obj = (string_target_kind, unit) prim_token_notation_obj
type prim_token_interp_info =
Uid of prim_token_uid
- | NumeralNotation of numeral_notation_obj
+ | NumberNotation of number_notation_obj
| StringNotation of string_notation_obj
type prim_token_infos = {
pt_local : bool; (** Is this interpretation local? *)
pt_scope : scope_name; (** Concerned scope *)
- pt_interp_info : prim_token_interp_info; (** Unique id "pointing" to (un)interp functions, OR a numeral notation object describing (un)interp functions *)
+ pt_interp_info : prim_token_interp_info; (** Unique id "pointing" to (un)interp functions, OR a number notation object describing (un)interp functions *)
pt_required : required_module; (** Module that should be loaded first *)
pt_refs : GlobRef.t list; (** Entry points during uninterpretation *)
pt_in_match : bool (** Is this prim token legal in match patterns ? *)
@@ -234,7 +251,7 @@ type notation_use =
| OnlyParsing
| ParsingAndPrinting
-val declare_uninterpretation : interp_rule -> interpretation -> unit
+val declare_uninterpretation : ?also_in_cases_pattern:bool -> interp_rule -> interpretation -> unit
type entry_coercion_kind =
| IsEntryCoercion of notation_entry_level
@@ -243,6 +260,7 @@ type entry_coercion_kind =
val declare_notation : notation_with_optional_scope * notation ->
interpretation -> notation_location -> use:notation_use ->
+ also_in_cases_pattern:bool ->
entry_coercion_kind option ->
Deprecation.t option -> unit
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index fe874cd01d..2e3fa0aa0e 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -941,7 +941,7 @@ let bind_term_as_binding_env alp (terms,termlists,binders,binderlists as sigma)
try
(* If already bound to a term, unify the binder and the term *)
match DAst.get (Id.List.assoc var terms) with
- | GVar id' ->
+ | GVar id' | GRef (GlobRef.VarRef id',None) ->
(if not (Id.equal id id') then (fst alp,(id,id')::snd alp) else alp),
sigma
| t ->
@@ -1147,16 +1147,22 @@ let does_not_come_from_already_eta_expanded_var glob =
(* checked). *)
match DAst.get glob with GVar _ -> false | _ -> true
+let is_var_term = function
+ (* The kind of expressions allowed to be both a term and a binding variable *)
+ | GVar _ -> true
+ | GRef (GlobRef.VarRef _,None) -> true
+ | _ -> false
+
let rec match_ inner u alp metas sigma a1 a2 =
let open CAst in
let loc = a1.loc in
match DAst.get a1, a2 with
(* Matching notation variable *)
| r1, NVar id2 when is_term_meta id2 metas -> bind_term_env alp sigma id2 a1
- | GVar _, NVar id2 when is_onlybinding_pattern_like_meta true id2 metas -> bind_binding_as_term_env alp sigma id2 a1
+ | r1, NVar id2 when is_var_term r1 && is_onlybinding_pattern_like_meta true id2 metas -> bind_binding_as_term_env alp sigma id2 a1
| r1, NVar id2 when is_onlybinding_pattern_like_meta false id2 metas -> bind_binding_as_term_env alp sigma id2 a1
- | GVar _, NVar id2 when is_onlybinding_strict_meta id2 metas -> raise No_match
- | GVar _, NVar id2 when is_onlybinding_meta id2 metas -> bind_binding_as_term_env alp sigma id2 a1
+ | r1, NVar id2 when is_var_term r1 && is_onlybinding_strict_meta id2 metas -> raise No_match
+ | r1, NVar id2 when is_var_term r1 && is_onlybinding_meta id2 metas -> bind_binding_as_term_env alp sigma id2 a1
| r1, NVar id2 when is_bindinglist_meta id2 metas -> bind_term_env alp sigma id2 a1
(* Matching recursive notations for terms *)
@@ -1436,9 +1442,8 @@ let reorder_canonically_substitution terms termlists metas =
List.fold_right (fun (x,(scl,typ)) (terms',termlists') ->
match typ with
| NtnTypeConstr -> ((Id.List.assoc x terms, scl)::terms',termlists')
- | NtnTypeBinder _ -> assert false
| NtnTypeConstrList -> (terms',(Id.List.assoc x termlists,scl)::termlists')
- | NtnTypeBinderList -> assert false)
+ | NtnTypeBinder _ | NtnTypeBinderList -> anomaly (str "Unexpected binder in pattern notation."))
metas ([],[])
let match_notation_constr_cases_pattern c (metas,pat) =
diff --git a/interp/numTok.mli b/interp/numTok.mli
index bcfe663dd2..386a25f042 100644
--- a/interp/numTok.mli
+++ b/interp/numTok.mli
@@ -8,20 +8,20 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-(** Numerals in different forms: signed or unsigned, possibly with
+(** Numbers in different forms: signed or unsigned, possibly with
fractional part and exponent.
- Numerals are represented using raw strings of (hexa)decimal
+ Numbers are represented using raw strings of (hexa)decimal
literals 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
+ The reason to keep the number exactly as it was parsed is that
+ specific notations can be declared for specific numbers
(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. *)
+ interpretation as number. So, one has to record the form of the
+ number which exactly matches the notation. *)
type sign = SPlus | SMinus
@@ -44,7 +44,7 @@ sig
val sprint : t -> string
val print : t -> Pp.t
- (** [sprint] and [print] returns the numeral as it was parsed, for printing *)
+ (** [sprint] and [print] returns the number as it was parsed, for printing *)
val classify : t -> num_class
@@ -69,7 +69,7 @@ sig
val to_bigint : t -> Z.t
end
-(** {6 Unsigned decimal numerals } *)
+(** {6 Unsigned decimal numbers } *)
module Unsigned :
sig
@@ -80,12 +80,12 @@ sig
val sprint : t -> string
val print : t -> Pp.t
- (** [sprint] and [print] returns the numeral as it was parsed, for printing *)
+ (** [sprint] and [print] returns the number as it was parsed, for printing *)
val parse : char Stream.t -> t
- (** Parse a positive Coq numeral.
+ (** Parse a positive Coq number.
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.
+ Precondition: at least two extra chars after the number to parse.
The recognized syntax is:
- integer part: \[0-9\]\[0-9_\]*
@@ -97,13 +97,13 @@ sig
- exponent part: empty or \[pP\]\[+-\]?\[0-9\]\[0-9_\]* *)
val parse_string : string -> t option
- (** Parse the string as a non negative Coq numeral, if possible *)
+ (** Parse the string as a non negative Coq number, if possible *)
val classify : t -> num_class
end
-(** {6 Signed decimal numerals } *)
+(** {6 Signed decimal numbers } *)
module Signed :
sig
@@ -117,10 +117,10 @@ sig
val sprint : t -> string
val print : t -> Pp.t
- (** [sprint] and [print] returns the numeral as it was parsed, for printing *)
+ (** [sprint] and [print] returns the number as it was parsed, for printing *)
val parse_string : string -> t option
- (** Parse the string as a signed Coq numeral, if possible *)
+ (** Parse the string as a signed Coq number, if possible *)
val of_int_string : string -> t
(** Convert from a string in the syntax of OCaml's int/int64 *)
diff --git a/interp/smartlocate.ml b/interp/smartlocate.ml
index 33d8aa6064..46baa00c74 100644
--- a/interp/smartlocate.ml
+++ b/interp/smartlocate.ml
@@ -50,6 +50,16 @@ let locate_global_with_alias ?(head=false) qid =
user_err ?loc:qid.CAst.loc (pr_qualid qid ++
str " is bound to a notation that does not denote a reference.")
+let global_constant_with_alias qid =
+ try match locate_global_with_alias qid with
+ | Names.GlobRef.ConstRef c -> c
+ | ref ->
+ user_err ?loc:qid.CAst.loc ~hdr:"global_inductive"
+ (pr_qualid qid ++ spc () ++ str "is not a reference to a constant.")
+ with Not_found as exn ->
+ let _, info = Exninfo.capture exn in
+ Nametab.error_global_not_found ~info qid
+
let global_inductive_with_alias qid =
try match locate_global_with_alias qid with
| Names.GlobRef.IndRef ind -> ind
@@ -60,6 +70,16 @@ let global_inductive_with_alias qid =
let _, info = Exninfo.capture exn in
Nametab.error_global_not_found ~info qid
+let global_constructor_with_alias qid =
+ try match locate_global_with_alias qid with
+ | Names.GlobRef.ConstructRef c -> c
+ | ref ->
+ user_err ?loc:qid.CAst.loc ~hdr:"global_inductive"
+ (pr_qualid qid ++ spc () ++ str "is not a constructor of an inductive type.")
+ with Not_found as exn ->
+ let _, info = Exninfo.capture exn in
+ Nametab.error_global_not_found ~info qid
+
let global_with_alias ?head qid =
try locate_global_with_alias ?head qid
with Not_found as exn ->
@@ -72,9 +92,17 @@ let smart_global ?(head = false) = let open Constrexpr in CAst.with_loc_val (fun
| ByNotation (ntn,sc) ->
Notation.interp_notation_as_global_reference ?loc ~head (fun _ -> true) ntn sc)
-let smart_global_inductive = let open Constrexpr in CAst.with_loc_val (fun ?loc -> function
- | AN r ->
- global_inductive_with_alias r
+let smart_global_kind f dest is = let open Constrexpr in CAst.with_loc_val (fun ?loc -> function
+ | AN r -> f r
| ByNotation (ntn,sc) ->
- destIndRef
- (Notation.interp_notation_as_global_reference ?loc ~head:false isIndRef ntn sc))
+ dest
+ (Notation.interp_notation_as_global_reference ?loc ~head:false is ntn sc))
+
+let smart_global_constant =
+ smart_global_kind global_constant_with_alias destConstRef isConstRef
+
+let smart_global_inductive =
+ smart_global_kind global_inductive_with_alias destIndRef isIndRef
+
+let smart_global_constructor =
+ smart_global_kind global_constructor_with_alias destConstructRef isConstructRef
diff --git a/interp/smartlocate.mli b/interp/smartlocate.mli
index 9b24a62086..26f2a4f36d 100644
--- a/interp/smartlocate.mli
+++ b/interp/smartlocate.mli
@@ -28,11 +28,23 @@ val global_of_extended_global : extended_global_reference -> GlobRef.t
a reference. *)
val global_with_alias : ?head:bool -> qualid -> GlobRef.t
+(** The same for constants *)
+val global_constant_with_alias : qualid -> Constant.t
+
(** The same for inductive types *)
val global_inductive_with_alias : qualid -> inductive
+(** The same for constructors of an inductive type *)
+val global_constructor_with_alias : qualid -> constructor
+
(** Locate a reference taking into account notations and "aliases" *)
val smart_global : ?head:bool -> qualid Constrexpr.or_by_notation -> GlobRef.t
+(** The same for constants *)
+val smart_global_constant : qualid Constrexpr.or_by_notation -> Constant.t
+
(** The same for inductive types *)
val smart_global_inductive : qualid Constrexpr.or_by_notation -> inductive
+
+(** The same for constructors of an inductive type *)
+val smart_global_constructor : qualid Constrexpr.or_by_notation -> constructor
diff --git a/interp/syntax_def.ml b/interp/syntax_def.ml
index bd3e234a91..f3ad3546ff 100644
--- a/interp/syntax_def.ml
+++ b/interp/syntax_def.ml
@@ -22,6 +22,7 @@ type syndef =
{ syndef_pattern : interpretation;
syndef_onlyparsing : bool;
syndef_deprecation : Deprecation.t option;
+ syndef_also_in_cases_pattern : bool;
}
let syntax_table =
@@ -52,7 +53,7 @@ let open_syntax_constant i ((sp,kn),(_local,syndef)) =
if not syndef.syndef_onlyparsing then
(* Redeclare it to be used as (short) name in case an other (distfix)
notation was declared in between *)
- Notation.declare_uninterpretation (Notation.SynDefRule kn) pat
+ Notation.declare_uninterpretation ~also_in_cases_pattern:syndef.syndef_also_in_cases_pattern (Notation.SynDefRule kn) pat
end
let cache_syntax_constant d =
@@ -81,11 +82,12 @@ let in_syntax_constant : (bool * syndef) -> obj =
subst_function = subst_syntax_constant;
classify_function = classify_syntax_constant }
-let declare_syntactic_definition ~local deprecation id ~onlyparsing pat =
+let declare_syntactic_definition ~local ?(also_in_cases_pattern=true) deprecation id ~onlyparsing pat =
let syndef =
{ syndef_pattern = pat;
syndef_onlyparsing = onlyparsing;
syndef_deprecation = deprecation;
+ syndef_also_in_cases_pattern = also_in_cases_pattern;
}
in
let _ = add_leaf id (in_syntax_constant (local,syndef)) in ()
diff --git a/interp/syntax_def.mli b/interp/syntax_def.mli
index 66a3132f2a..31f685152c 100644
--- a/interp/syntax_def.mli
+++ b/interp/syntax_def.mli
@@ -13,7 +13,7 @@ open Notation_term
(** Syntactic definitions. *)
-val declare_syntactic_definition : local:bool -> Deprecation.t option -> Id.t ->
+val declare_syntactic_definition : local:bool -> ?also_in_cases_pattern:bool -> Deprecation.t option -> Id.t ->
onlyparsing:bool -> interpretation -> unit
val search_syntactic_definition : ?loc:Loc.t -> KerName.t -> interpretation
diff --git a/kernel/cClosure.ml b/kernel/cClosure.ml
index a23ef8fdca..17feeb9b5a 100644
--- a/kernel/cClosure.ml
+++ b/kernel/cClosure.ml
@@ -1098,14 +1098,8 @@ module FNativeEntries =
let defined_array = ref false
- let farray = ref dummy
-
let init_array retro =
- match retro.Retroknowledge.retro_array with
- | Some c ->
- defined_array := true;
- farray := { mark = mark Norm KnownR; term = FFlex (ConstKey (Univ.in_punivs c)) }
- | None -> defined_array := false
+ defined_array := Option.has_some retro.Retroknowledge.retro_array
let init env =
current_retro := env.retroknowledge;
@@ -1165,7 +1159,7 @@ module FNativeEntries =
let mkFloat env f =
check_float env;
- { mark = mark Norm KnownR; term = FFloat f }
+ { mark = mark Cstr KnownR; term = FFloat f }
let mkBool env b =
check_bool env;
@@ -1328,10 +1322,14 @@ let rec knr info tab m stk =
| FFlex(ConstKey (kn,_u as c)) when red_set info.i_flags (fCONST kn) ->
(match ref_value_cache info tab (ConstKey c) with
| Def v -> kni info tab v stk
- | Primitive op when check_native_args op stk ->
- let rargs, a, nargs, stk = get_native_args1 op c stk in
- kni info tab a (Zprimitive(op,c,rargs,nargs)::stk)
- | Undef _ | OpaqueDef _ | Primitive _ -> (set_norm m; (m,stk)))
+ | Primitive op ->
+ if check_native_args op stk then
+ let rargs, a, nargs, stk = get_native_args1 op c stk in
+ kni info tab a (Zprimitive(op,c,rargs,nargs)::stk)
+ else
+ (* Similarly to fix, partially applied primitives are not Norm! *)
+ (m, stk)
+ | Undef _ | OpaqueDef _ -> (set_norm m; (m,stk)))
| FFlex(VarKey id) when red_set info.i_flags (fVAR id) ->
(match ref_value_cache info tab (VarKey id) with
| Def v -> kni info tab v stk
@@ -1531,7 +1529,12 @@ let whd_stack infos tab m stk = match Mark.red_state m.mark with
knh infos m stk
| Red | Cstr ->
let k = kni infos tab m stk in
- let () = if infos.i_cache.i_share then ignore (fapp_stack k) in (* to unlock Zupdates! *)
+ let () =
+ if infos.i_cache.i_share then
+ (* to unlock Zupdates! *)
+ let (m', stk') = k in
+ if not (m == m' && stk == stk') then ignore (zip m' stk')
+ in
k
let create_clos_infos ?univs ?(evars=fun _ -> None) flgs env =
diff --git a/kernel/environ.ml b/kernel/environ.ml
index 17c5a02e2b..69edb1498c 100644
--- a/kernel/environ.ml
+++ b/kernel/environ.ml
@@ -43,7 +43,6 @@ type key = int CEphemeron.key option ref
type link_info =
| Linked of string
- | LinkedInteractive of string
| NotLinked
type constant_key = Opaqueproof.opaque constant_body * (link_info ref * key)
@@ -104,7 +103,6 @@ type env = {
env_typing_flags : typing_flags;
retroknowledge : Retroknowledge.retroknowledge;
indirect_pterms : Opaqueproof.opaquetab;
- native_symbols : Nativevalues.symbols DPmap.t;
}
let empty_named_context_val = {
@@ -136,7 +134,6 @@ let empty_env = {
env_typing_flags = Declareops.safe_flags Conv_oracle.empty;
retroknowledge = Retroknowledge.empty;
indirect_pterms = Opaqueproof.empty_opaquetab;
- native_symbols = DPmap.empty;
}
@@ -571,6 +568,11 @@ let is_primitive env c =
| Declarations.Primitive _ -> true
| _ -> false
+let is_array_type env c =
+ match env.retroknowledge.Retroknowledge.retro_array with
+ | None -> false
+ | Some c' -> Constant.CanOrd.equal c c'
+
let polymorphic_constant cst env =
Declareops.constant_is_polymorphic (lookup_constant cst env)
@@ -829,10 +831,6 @@ let is_type_in_type env r =
let set_retroknowledge env r = { env with retroknowledge = r }
-let set_native_symbols env native_symbols = { env with native_symbols }
-let add_native_symbols dir syms env =
- { env with native_symbols = DPmap.add dir syms env.native_symbols }
-
module type QNameS =
sig
type t
diff --git a/kernel/environ.mli b/kernel/environ.mli
index f0b40e6492..6a8ddce835 100644
--- a/kernel/environ.mli
+++ b/kernel/environ.mli
@@ -37,7 +37,6 @@ val dummy_lazy_val : unit -> lazy_val
(** Linking information for the native compiler *)
type link_info =
| Linked of string
- | LinkedInteractive of string
| NotLinked
type key = int CEphemeron.key option ref
@@ -90,7 +89,6 @@ type env = private {
env_typing_flags : typing_flags;
retroknowledge : Retroknowledge.retroknowledge;
indirect_pterms : Opaqueproof.opaquetab;
- native_symbols : Nativevalues.symbols DPmap.t;
}
val oracle : env -> Conv_oracle.oracle
@@ -251,6 +249,8 @@ val constant_opt_value_in : env -> Constant.t puniverses -> constr option
val is_primitive : env -> Constant.t -> bool
+val is_array_type : env -> Constant.t -> bool
+
(** {6 Primitive projections} *)
(** Checks that the number of parameters is correct. *)
@@ -414,6 +414,3 @@ val no_link_info : link_info
(** Primitives *)
val set_retroknowledge : env -> Retroknowledge.retroknowledge -> env
-
-val set_native_symbols : env -> Nativevalues.symbols DPmap.t -> env
-val add_native_symbols : DirPath.t -> Nativevalues.symbols -> env -> env
diff --git a/kernel/names.ml b/kernel/names.ml
index 5b6064fa9f..13761ca245 100644
--- a/kernel/names.ml
+++ b/kernel/names.ml
@@ -44,6 +44,10 @@ struct
| None -> true
| Some _ -> false
+ let is_valid_ident_part s = match Unicode.ident_refutation ("x"^s) with
+ | None -> true
+ | Some _ -> false
+
let of_bytes s =
let s = Bytes.to_string s in
check_valid s;
diff --git a/kernel/names.mli b/kernel/names.mli
index 9a4ceef802..74a4e6f7d0 100644
--- a/kernel/names.mli
+++ b/kernel/names.mli
@@ -44,6 +44,9 @@ sig
val is_valid : string -> bool
(** Check that a string may be converted to an identifier. *)
+ val is_valid_ident_part : string -> bool
+ (** Check that a string is a valid part of an identifier *)
+
val of_bytes : bytes -> t
val of_string : string -> t
(** Converts a string into an identifier.
diff --git a/kernel/nativecode.ml b/kernel/nativecode.ml
index b5c4d6416a..09db29d222 100644
--- a/kernel/nativecode.ml
+++ b/kernel/nativecode.ml
@@ -1933,7 +1933,7 @@ and compile_named env sigma univ auxdefs id =
| LocalAssum _ ->
Glet(Gnamed id, MLprimitive (Mk_var id))::auxdefs
-let compile_constant env sigma prefix ~interactive con cb =
+let compile_constant env sigma con cb =
let no_univs = 0 = Univ.AUContext.size (Declareops.constant_polymorphic_context cb) in
begin match cb.const_body with
| Def t ->
@@ -1942,10 +1942,6 @@ let compile_constant env sigma prefix ~interactive con cb =
if !Flags.debug then Feedback.msg_debug (Pp.str "Generated lambda code");
let is_lazy = is_lazy t in
let code = if is_lazy then mk_lazy code else code in
- let name =
- if interactive then LinkedInteractive prefix
- else Linked prefix
- in
let l = Constant.label con in
let auxdefs,code =
if no_univs then compile_with_fv env sigma None [] (Some l) code
@@ -1959,7 +1955,7 @@ let compile_constant env sigma prefix ~interactive con cb =
optimize_stk (Glet(Gconstant ("", con),code)::auxdefs)
in
if !Flags.debug then Feedback.msg_debug (Pp.str "Optimized mllambda code");
- code, name
+ code
| _ ->
let i = push_symbol (SymbConst con) in
let args =
@@ -1969,9 +1965,7 @@ let compile_constant env sigma prefix ~interactive con cb =
(*
let t = mkMLlam [|univ|] (mkMLapp (MLprimitive Mk_const)
*)
- [Glet(Gconstant ("", con), mkMLapp (MLprimitive Mk_const) args)],
- if interactive then LinkedInteractive prefix
- else Linked prefix
+ [Glet(Gconstant ("", con), mkMLapp (MLprimitive Mk_const) args)]
end
module StringOrd = struct type t = string let compare = String.compare end
@@ -1984,12 +1978,9 @@ let is_loaded_native_file s = StringSet.mem s !loaded_native_files
let register_native_file s =
loaded_native_files := StringSet.add s !loaded_native_files
-let is_code_loaded ~interactive name =
+let is_code_loaded name =
match !name with
| NotLinked -> false
- | LinkedInteractive s ->
- if (interactive && is_loaded_native_file s) then true
- else (name := NotLinked; false)
| Linked s ->
if is_loaded_native_file s then true
else (name := NotLinked; false)
@@ -2049,8 +2040,11 @@ let compile_mind mb mind stack =
in
Array.fold_left_i f stack mb.mind_packets
-type code_location_update =
- link_info ref * link_info
+type code_location_update = {
+ upd_info : link_info ref;
+ upd_prefix : string;
+}
+
type code_location_updates =
code_location_update Mindmap_env.t * code_location_update Cmap_env.t
@@ -2058,35 +2052,34 @@ type linkable_code = global list * code_location_updates
let empty_updates = Mindmap_env.empty, Cmap_env.empty
-let compile_mind_deps env prefix ~interactive
+let compile_mind_deps env prefix
(comp_stack, (mind_updates, const_updates) as init) mind =
let mib,nameref = lookup_mind_key mind env in
- if is_code_loaded ~interactive nameref
+ if is_code_loaded nameref
|| Mindmap_env.mem mind mind_updates
then init
else
let comp_stack =
compile_mind mib mind comp_stack
in
- let name =
- if interactive then LinkedInteractive prefix
- else Linked prefix
- in
- let upd = (nameref, name) in
+ let upd = {
+ upd_info = nameref;
+ upd_prefix = prefix;
+ } in
let mind_updates = Mindmap_env.add mind upd mind_updates in
(comp_stack, (mind_updates, const_updates))
(* This function compiles all necessary dependencies of t, and generates code in
reverse order, as well as linking information updates *)
-let compile_deps env sigma prefix ~interactive init t =
+let compile_deps env sigma prefix init t =
let rec aux env lvl init t =
match kind t with
- | Ind ((mind,_),_u) -> compile_mind_deps env prefix ~interactive init mind
+ | Ind ((mind,_),_u) -> compile_mind_deps env prefix init mind
| Const c ->
let c,_u = get_alias env c in
let cb,(nameref,_) = lookup_constant_key c env in
let (_, (_, const_updates)) = init in
- if is_code_loaded ~interactive nameref
+ if is_code_loaded nameref
|| (Cmap_env.mem c const_updates)
then init
else
@@ -2096,19 +2089,21 @@ let compile_deps env sigma prefix ~interactive init t =
aux env lvl init (Mod_subst.force_constr t)
| _ -> init
in
- let code, name =
- compile_constant env sigma prefix ~interactive c cb
- in
+ let code = compile_constant env sigma c cb in
+ let upd = {
+ upd_info = nameref;
+ upd_prefix = prefix;
+ } in
let comp_stack = code@comp_stack in
- let const_updates = Cmap_env.add c (nameref, name) const_updates in
+ let const_updates = Cmap_env.add c upd const_updates in
comp_stack, (mind_updates, const_updates)
- | Construct (((mind,_),_),_u) -> compile_mind_deps env prefix ~interactive init mind
+ | Construct (((mind,_),_),_u) -> compile_mind_deps env prefix init mind
| Proj (p,c) ->
- let init = compile_mind_deps env prefix ~interactive init (Projection.mind p) in
+ let init = compile_mind_deps env prefix init (Projection.mind p) in
aux env lvl init c
| Case (ci, _p, _iv, _c, _ac) ->
let mind = fst ci.ci_ind in
- let init = compile_mind_deps env prefix ~interactive init mind in
+ let init = compile_mind_deps env prefix init mind in
fold_constr_with_binders succ (aux env) lvl init t
| Var id ->
let open Context.Named.Declaration in
@@ -2130,11 +2125,8 @@ let compile_deps env sigma prefix ~interactive init t =
in
aux env 0 init t
-let compile_constant_field env prefix con acc cb =
- let (gl, _) =
- compile_constant ~interactive:false env empty_evars prefix
- con cb
- in
+let compile_constant_field env _prefix con acc cb =
+ let gl = compile_constant env empty_evars con cb in
gl@acc
let compile_mind_field mp l acc mb =
@@ -2152,11 +2144,11 @@ let mk_conv_code env sigma prefix t1 t2 =
clear_global_tbl ();
let gl, (mind_updates, const_updates) =
let init = ([], empty_updates) in
- compile_deps env sigma prefix ~interactive:true init t1
+ compile_deps env sigma prefix init t1
in
let gl, (mind_updates, const_updates) =
let init = (gl, (mind_updates, const_updates)) in
- compile_deps env sigma prefix ~interactive:true init t2
+ compile_deps env sigma prefix init t2
in
let code1 = lambda_of_constr env sigma t1 in
let code2 = lambda_of_constr env sigma t2 in
@@ -2179,7 +2171,7 @@ let mk_norm_code env sigma prefix t =
clear_global_tbl ();
let gl, (mind_updates, const_updates) =
let init = ([], empty_updates) in
- compile_deps env sigma prefix ~interactive:true init t
+ compile_deps env sigma prefix init t
in
let code = lambda_of_constr env sigma t in
let (gl,code) = compile_with_fv env sigma None gl None code in
@@ -2192,13 +2184,12 @@ let mk_norm_code env sigma prefix t =
[|MLglobal (Ginternal "()")|])) in
header::gl, (mind_updates, const_updates)
-let mk_library_header dir =
- let libname = Format.sprintf "(str_decode \"%s\")" (str_encode dir) in
- [Glet(Ginternal "symbols_tbl",
- MLapp (MLglobal (Ginternal "get_library_native_symbols"),
- [|MLglobal (Ginternal libname)|]))]
+let mk_library_header (symbols : Nativevalues.symbols) =
+ let symbols = Format.sprintf "(str_decode \"%s\")" (str_encode symbols) in
+ [Glet(Ginternal "symbols_tbl", MLglobal (Ginternal symbols))]
-let update_location (r,v) = r := v
+let update_location r =
+ r.upd_info := Linked r.upd_prefix
let update_locations (ind_updates,const_updates) =
Mindmap_env.iter (fun _ -> update_location) ind_updates;
diff --git a/kernel/nativecode.mli b/kernel/nativecode.mli
index 71317d188b..aab6e1d4a0 100644
--- a/kernel/nativecode.mli
+++ b/kernel/nativecode.mli
@@ -50,7 +50,6 @@ val get_proj : symbols -> int -> inductive * int
val get_symbols : unit -> symbols
-type code_location_update
type code_location_updates
type linkable_code = global list * code_location_updates
@@ -69,7 +68,7 @@ val compile_mind_field : ModPath.t -> Label.t ->
val mk_conv_code : env -> evars -> string -> constr -> constr -> linkable_code
val mk_norm_code : env -> evars -> string -> constr -> linkable_code
-val mk_library_header : DirPath.t -> global list
+val mk_library_header : Nativevalues.symbols -> global list
val mod_uid_of_dirpath : DirPath.t -> string
diff --git a/kernel/nativeconv.ml b/kernel/nativeconv.ml
index 76215b4386..d77ee759c6 100644
--- a/kernel/nativeconv.ml
+++ b/kernel/nativeconv.ml
@@ -161,7 +161,7 @@ let native_conv_gen pb sigma env univs t1 t2 =
let fn = compile ml_filename code ~profile:false in
if !Flags.debug then Feedback.msg_debug (Pp.str "Running test...");
let t0 = Sys.time () in
- call_linker env ~fatal:true ~prefix fn (Some upds);
+ call_linker ~fatal:true ~prefix fn (Some upds);
let t1 = Sys.time () in
let time_info = Format.sprintf "Evaluation done in %.5f@." (t1 -. t0) in
if !Flags.debug then Feedback.msg_debug (Pp.str time_info);
diff --git a/kernel/nativelambda.ml b/kernel/nativelambda.ml
index e98e97907a..18f16f427d 100644
--- a/kernel/nativelambda.ml
+++ b/kernel/nativelambda.ml
@@ -111,14 +111,12 @@ let get_mind_prefix env mind =
match !name with
| NotLinked -> ""
| Linked s -> s
- | LinkedInteractive s -> s
let get_const_prefix env c =
let _,(nameref,_) = lookup_constant_key c env in
match !nameref with
| NotLinked -> ""
| Linked s -> s
- | LinkedInteractive s -> s
(* A generic map function *)
diff --git a/kernel/nativelib.ml b/kernel/nativelib.ml
index 494282d4e1..1e1085d5ff 100644
--- a/kernel/nativelib.ml
+++ b/kernel/nativelib.ml
@@ -25,7 +25,8 @@ let open_header = ["Nativevalues";
let open_header = List.map mk_open open_header
(* Directory where compiled files are stored *)
-let output_dir = ref ".coq-native"
+let dft_output_dir = ".coq-native"
+let output_dir = ref dft_output_dir
(* Extension of generated ml files, stored for debugging purposes *)
let source_ext = ".native"
@@ -92,9 +93,14 @@ let error_native_compiler_failed e =
CErrors.user_err msg
let call_compiler ?profile:(profile=false) ml_filename =
- let load_path = !get_load_paths () in
- let load_path = List.map (fun dn -> dn / !output_dir) load_path in
- let include_dirs = List.flatten (List.map (fun x -> ["-I"; x]) (get_include_dirs () @ load_path)) in
+ (* The below path is computed from Require statements, by uniquizing
+ the paths, see [Library.get_used_load_paths] This is in general
+ hacky and we should do a bit better once we move loadpath to its
+ own library *)
+ let require_load_path = !get_load_paths () in
+ (* We assume that installed files always go in .coq-native for now *)
+ let install_load_path = List.map (fun dn -> dn / dft_output_dir) require_load_path in
+ let include_dirs = List.flatten (List.map (fun x -> ["-I"; x]) (get_include_dirs () @ install_load_path)) in
let f = Filename.chop_extension ml_filename in
let link_filename = f ^ ".cmo" in
let link_filename = Dynlink.adapt_filename link_filename in
@@ -139,8 +145,10 @@ let compile fn code ~profile:profile =
if (not !Flags.debug) && Sys.file_exists fn then Sys.remove fn;
r
-let compile_library dir code fn =
- let header = mk_library_header dir in
+type native_library = Nativecode.global list * Nativevalues.symbols
+
+let compile_library (code, symb) fn =
+ let header = mk_library_header symb in
let fn = fn ^ source_ext in
let basename = Filename.basename fn in
let dirname = Filename.dirname fn in
@@ -154,19 +162,9 @@ let compile_library dir code fn =
let _ = call_compiler fn in
if (not !Flags.debug) && Sys.file_exists fn then Sys.remove fn
-let native_symbols = ref Names.DPmap.empty
-
-let get_library_native_symbols dir =
- try Names.DPmap.find dir !native_symbols
- with Not_found ->
- CErrors.user_err ~hdr:"get_library_native_symbols"
- Pp.((str "Linker error in the native compiler. Are you using Require inside a nested Module declaration?") ++ fnl () ++
- (str "This use case is not supported, but disabling the native compiler may help."))
-
(* call_linker links dynamically the code for constants in environment or a *)
(* conversion test. *)
-let call_linker ?(fatal=true) env ~prefix f upds =
- native_symbols := env.Environ.native_symbols;
+let call_linker ?(fatal=true) ~prefix f upds =
rt1 := dummy_value ();
rt2 := dummy_value ();
if not (Sys.file_exists f) then
@@ -185,6 +183,11 @@ let call_linker ?(fatal=true) env ~prefix f upds =
else if !Flags.debug then Feedback.msg_debug CErrors.(iprint exn));
match upds with Some upds -> update_locations upds | _ -> ()
-let link_library env ~prefix ~dirname ~basename =
- let f = dirname / !output_dir / basename in
- call_linker env ~fatal:false ~prefix f None
+let link_library ~prefix ~dirname ~basename =
+ (* We try both [output_dir] and [.coq-native], unfortunately from
+ [Require] we don't know if we are loading a library in the build
+ dir or in the installed layout *)
+ let install_location = dirname / dft_output_dir / basename in
+ let build_location = dirname / !output_dir / basename in
+ let f = if Sys.file_exists build_location then build_location else install_location in
+ call_linker ~fatal:false ~prefix f None
diff --git a/kernel/nativelib.mli b/kernel/nativelib.mli
index 29b4d20197..0c0fe3acc9 100644
--- a/kernel/nativelib.mli
+++ b/kernel/nativelib.mli
@@ -27,27 +27,24 @@ val get_ml_filename : unit -> string * string
whether are in byte mode or not; file is expected to be .ml file *)
val compile : string -> global list -> profile:bool -> string
-(** [compile_library lib code file] is similar to [compile file code]
+type native_library = Nativecode.global list * Nativevalues.symbols
+
+(** [compile_library (code, _) file] is similar to [compile file code]
but will perform some extra tweaks to handle [code] as a Coq lib. *)
-val compile_library : Names.DirPath.t -> global list -> string -> unit
+val compile_library : native_library -> string -> unit
val call_linker
: ?fatal:bool
- -> Environ.env
-> prefix:string
-> string
-> code_location_updates option
-> unit
val link_library
- : Environ.env
- -> prefix:string
+ : prefix:string
-> dirname:string
-> basename:string
-> unit
val rt1 : Nativevalues.t ref
val rt2 : Nativevalues.t ref
-
-val get_library_native_symbols : Names.DirPath.t -> Nativevalues.symbols
-(** Strictly for usage by code produced by native compute. *)
diff --git a/kernel/reduction.ml b/kernel/reduction.ml
index 5589ae3483..cf40263f61 100644
--- a/kernel/reduction.ml
+++ b/kernel/reduction.ml
@@ -280,11 +280,12 @@ let convert_constructors ctor nargs u1 u2 (s, check) =
convert_constructors_gen (check.compare_instances ~flex:false) check.compare_cumul_instances
ctor nargs u1 u2 s, check
-let conv_table_key infos k1 k2 cuniv =
+let conv_table_key infos ~nargs k1 k2 cuniv =
if k1 == k2 then cuniv else
match k1, k2 with
| ConstKey (cst, u), ConstKey (cst', u') when Constant.CanOrd.equal cst cst' ->
if Univ.Instance.equal u u' then cuniv
+ else if Int.equal nargs 1 && is_array_type (info_env infos) cst then cuniv
else
let flex = evaluable_constant cst (info_env infos)
&& RedFlags.red_set (info_flags infos) (RedFlags.fCONST cst)
@@ -301,9 +302,14 @@ let unfold_ref_with_args infos tab fl v =
| Primitive op when check_native_args op v ->
let c = match fl with ConstKey c -> c | _ -> assert false in
let rargs, a, nargs, v = get_native_args1 op c v in
- Some (whd_stack infos tab a (Zupdate a::(Zprimitive(op,c,rargs,nargs)::v)))
+ Some (a, (Zupdate a::(Zprimitive(op,c,rargs,nargs)::v)))
| Undef _ | OpaqueDef _ | Primitive _ -> None
+let same_args_size sk1 sk2 =
+ let n = CClosure.stack_args_size sk1 in
+ if Int.equal n (CClosure.stack_args_size sk2) then n
+ else raise NotConvertible
+
type conv_tab = {
cnv_inf : clos_infos;
lft_tab : clos_tab;
@@ -408,26 +414,30 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
(* 2 constants, 2 local defined vars or 2 defined rels *)
| (FFlex fl1, FFlex fl2) ->
(try
- let cuniv = conv_table_key infos.cnv_inf fl1 fl2 cuniv in
+ let nargs = same_args_size v1 v2 in
+ let cuniv = conv_table_key infos.cnv_inf ~nargs fl1 fl2 cuniv in
convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
with NotConvertible | Univ.UniverseInconsistency _ ->
- (* else the oracle tells which constant is to be expanded *)
- let oracle = CClosure.oracle_of_infos infos.cnv_inf in
- let (app1,app2) =
- let aux appr1 lft1 fl1 tab1 v1 appr2 lft2 fl2 tab2 v2 =
- match unfold_ref_with_args infos.cnv_inf tab1 fl1 v1 with
- | Some t1 -> ((lft1, t1), appr2)
- | None -> match unfold_ref_with_args infos.cnv_inf tab2 fl2 v2 with
- | Some t2 -> (appr1, (lft2, t2))
- | None -> raise NotConvertible
- in
- if Conv_oracle.oracle_order Univ.out_punivs oracle l2r fl1 fl2 then
- aux appr1 lft1 fl1 infos.lft_tab v1 appr2 lft2 fl2 infos.rgt_tab v2
- else
- let (app2,app1) = aux appr2 lft2 fl2 infos.rgt_tab v2 appr1 lft1 fl1 infos.lft_tab v1 in
- (app1,app2)
- in
- eqappr cv_pb l2r infos app1 app2 cuniv)
+ let r1 = unfold_ref_with_args infos.cnv_inf infos.lft_tab fl1 v1 in
+ let r2 = unfold_ref_with_args infos.cnv_inf infos.rgt_tab fl2 v2 in
+ match r1, r2 with
+ | None, None -> raise NotConvertible
+ | Some t1, Some t2 ->
+ (* else the oracle tells which constant is to be expanded *)
+ let oracle = CClosure.oracle_of_infos infos.cnv_inf in
+ if Conv_oracle.oracle_order Univ.out_punivs oracle l2r fl1 fl2 then
+ eqappr cv_pb l2r infos (lft1, t1) appr2 cuniv
+ else
+ eqappr cv_pb l2r infos appr1 (lft2, t2) cuniv
+ | Some (t1, v1), None ->
+ let all = RedFlags.red_add_transparent all (RedFlags.red_transparent (info_flags infos.cnv_inf)) in
+ let t1 = whd_stack (infos_with_reds infos.cnv_inf all) infos.lft_tab t1 v1 in
+ eqappr cv_pb l2r infos (lft1, t1) appr2 cuniv
+ | None, Some (t2, v2) ->
+ let all = RedFlags.red_add_transparent all (RedFlags.red_transparent (info_flags infos.cnv_inf)) in
+ let t2 = whd_stack (infos_with_reds infos.cnv_inf all) infos.rgt_tab t2 v2 in
+ eqappr cv_pb l2r infos appr1 (lft2, t2) cuniv
+ )
| (FProj (p1,c1), FProj (p2, c2)) ->
(* Projections: prefer unfolding to first-order unification,
@@ -574,17 +584,14 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else
let mind = Environ.lookup_mind (fst ind1) (info_env infos.cnv_inf) in
- let nargs = CClosure.stack_args_size v1 in
- if not (Int.equal nargs (CClosure.stack_args_size v2))
- then raise NotConvertible
- else
- match convert_inductives cv_pb (mind, snd ind1) nargs u1 u2 cuniv with
- | cuniv -> convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
- | exception MustExpand ->
- let env = info_env infos.cnv_inf in
- let hd1 = eta_expand_ind env pind1 in
- let hd2 = eta_expand_ind env pind2 in
- eqappr cv_pb l2r infos (lft1,(hd1,v1)) (lft2,(hd2,v2)) cuniv
+ let nargs = same_args_size v1 v2 in
+ match convert_inductives cv_pb (mind, snd ind1) nargs u1 u2 cuniv with
+ | cuniv -> convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ | exception MustExpand ->
+ let env = info_env infos.cnv_inf in
+ let hd1 = eta_expand_ind env pind1 in
+ let hd2 = eta_expand_ind env pind2 in
+ eqappr cv_pb l2r infos (lft1,(hd1,v1)) (lft2,(hd2,v2)) cuniv
else raise NotConvertible
| (FConstruct ((ind1,j1),u1 as pctor1), FConstruct ((ind2,j2),u2 as pctor2)) ->
@@ -594,17 +601,14 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else
let mind = Environ.lookup_mind (fst ind1) (info_env infos.cnv_inf) in
- let nargs = CClosure.stack_args_size v1 in
- if not (Int.equal nargs (CClosure.stack_args_size v2))
- then raise NotConvertible
- else
- match convert_constructors (mind, snd ind1, j1) nargs u1 u2 cuniv with
- | cuniv -> convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
- | exception MustExpand ->
- let env = info_env infos.cnv_inf in
- let hd1 = eta_expand_constructor env pctor1 in
- let hd2 = eta_expand_constructor env pctor2 in
- eqappr cv_pb l2r infos (lft1,(hd1,v1)) (lft2,(hd2,v2)) cuniv
+ let nargs = same_args_size v1 v2 in
+ match convert_constructors (mind, snd ind1, j1) nargs u1 u2 cuniv with
+ | cuniv -> convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ | exception MustExpand ->
+ let env = info_env infos.cnv_inf in
+ let hd1 = eta_expand_constructor env pctor1 in
+ let hd2 = eta_expand_constructor env pctor2 in
+ eqappr cv_pb l2r infos (lft1,(hd1,v1)) (lft2,(hd2,v2)) cuniv
else raise NotConvertible
(* Eta expansion of records *)
diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml
index 3dee3d2b2f..6abd283f6c 100644
--- a/kernel/safe_typing.ml
+++ b/kernel/safe_typing.ml
@@ -121,7 +121,6 @@ type compiled_library = {
comp_univs : Univ.ContextSet.t;
comp_deps : library_info array;
comp_enga : engagement;
- comp_natsymbs : Nativevalues.symbols
}
type reimport = compiled_library * Univ.ContextSet.t * vodigest
@@ -672,7 +671,7 @@ let inline_side_effects env body side_eff =
let side_eff = List.fold_left (fun accu (cb, _) -> cb :: accu) [] side_eff in
let side_eff = List.rev side_eff in
(** Most recent side-effects first in side_eff *)
- if List.is_empty side_eff then (body, Univ.ContextSet.empty, sigs)
+ if List.is_empty side_eff then (body, Univ.ContextSet.empty, sigs, 0)
else
(** Second step: compute the lifts and substitutions to apply *)
let cname c r = Context.make_annot (Name (Label.to_id (Constant.label c))) r in
@@ -726,10 +725,10 @@ let inline_side_effects env body side_eff =
else mkLetIn (na, b, ty, accu)
in
let body = List.fold_right fold_arg args body in
- (body, ctx, sigs)
+ (body, ctx, sigs, len - 1)
let inline_private_constants env ((body, ctx), side_eff) =
- let body, ctx',_ = inline_side_effects env body side_eff in
+ let body, ctx', _, _ = inline_side_effects env body side_eff in
let ctx' = Univ.ContextSet.union ctx ctx' in
(body, ctx')
@@ -881,11 +880,11 @@ let add_constant l decl senv =
match decl with
| OpaqueEntry ce ->
let handle env body eff =
- let body, uctx, signatures = inline_side_effects env body eff in
+ let body, uctx, signatures, skip = inline_side_effects env body eff in
let trusted = check_signatures senv signatures in
let trusted, uctx = match trusted with
| None -> 0, uctx
- | Some univs -> List.length signatures, Univ.ContextSet.union univs uctx
+ | Some univs -> skip, Univ.ContextSet.union univs uctx
in
body, uctx, trusted
in
@@ -1139,7 +1138,6 @@ let end_module l restype senv =
let mb, cst = build_module_body params restype senv in
let senv = push_context_set ~strict:true (Univ.LSet.empty,cst) senv in
let newenv = Environ.set_opaque_tables oldsenv.env (Environ.opaque_tables senv.env) in
- let newenv = Environ.set_native_symbols newenv senv.env.Environ.native_symbols in
let newenv = set_engagement_opt newenv senv.engagement in
let newenv = Environ.set_universes (Environ.universes senv.env) newenv in
let senv' = propagate_loads { senv with env = newenv } in
@@ -1166,7 +1164,6 @@ let end_modtype l senv =
let () = check_empty_context senv in
let mbids = List.rev_map fst params in
let newenv = Environ.set_opaque_tables oldsenv.env (Environ.opaque_tables senv.env) in
- let newenv = Environ.set_native_symbols newenv senv.env.Environ.native_symbols in
let newenv = set_engagement_opt newenv senv.engagement in
let newenv = Environ.set_universes (Environ.universes senv.env) newenv in
let senv' = propagate_loads {senv with env=newenv} in
@@ -1229,8 +1226,6 @@ let module_of_library lib = lib.comp_mod
let univs_of_library lib = lib.comp_univs
-type native_library = Nativecode.global list
-
(** FIXME: MS: remove?*)
let current_modpath senv = senv.modpath
let current_dirpath senv = Names.ModPath.dp (current_modpath senv)
@@ -1272,9 +1267,8 @@ let export ?except ~output_native_objects senv dir =
comp_univs = senv.univ;
comp_deps = Array.of_list (DPmap.bindings senv.required);
comp_enga = Environ.engagement senv.env;
- comp_natsymbs = symbols }
- in
- mp, lib, ast
+ } in
+ mp, lib, (ast, symbols)
(* cst are the constraints that were computed by the vi2vo step and hence are
* not part of the [lib.comp_univs] field (but morally should be) *)
@@ -1294,7 +1288,6 @@ let import lib cst vodigest senv =
let linkinfo = Nativecode.link_info_of_dirpath lib.comp_name in
Modops.add_linked_module mb linkinfo env
in
- let env = Environ.add_native_symbols lib.comp_name lib.comp_natsymbs env in
let sections =
Option.map (Section.map_custom (fun custom ->
{custom with rev_reimport = (lib,cst,vodigest) :: custom.rev_reimport}))
diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli
index b601279e87..6fa9022906 100644
--- a/kernel/safe_typing.mli
+++ b/kernel/safe_typing.mli
@@ -191,8 +191,6 @@ val current_dirpath : safe_environment -> DirPath.t
type compiled_library
-type native_library = Nativecode.global list
-
val module_of_library : compiled_library -> Declarations.module_body
val univs_of_library : compiled_library -> Univ.ContextSet.t
@@ -201,7 +199,7 @@ val start_library : DirPath.t -> ModPath.t safe_transformer
val export :
?except:Future.UUIDSet.t -> output_native_objects:bool ->
safe_environment -> DirPath.t ->
- ModPath.t * compiled_library * native_library
+ ModPath.t * compiled_library * Nativelib.native_library
(* Constraints are non empty iff the file is a vi2vo *)
val import : compiled_library -> Univ.ContextSet.t -> vodigest ->
diff --git a/kernel/vars.ml b/kernel/vars.ml
index f7e28b0cfe..a446fa413c 100644
--- a/kernel/vars.ml
+++ b/kernel/vars.ml
@@ -348,5 +348,8 @@ let universes_of_constr c =
| Array (u,_,_,_) ->
let s = LSet.fold LSet.add (Instance.levels u) s in
Constr.fold aux s c
+ | Case (_,_,CaseInvert {univs;args=_},_,_) ->
+ let s = LSet.fold LSet.add (Instance.levels univs) s in
+ Constr.fold aux s c
| _ -> Constr.fold aux s c
in aux LSet.empty c
diff --git a/lib/control.ml b/lib/control.ml
index bb42b5727e..95ea3935a7 100644
--- a/lib/control.ml
+++ b/lib/control.ml
@@ -18,10 +18,12 @@ let enable_thread_delay = ref false
let check_for_interrupt () =
if !interrupt then begin interrupt := false; raise Sys.Break end;
- incr steps;
- if !enable_thread_delay && !steps = 1000 then begin
- Thread.delay 0.001;
- steps := 0;
+ if !enable_thread_delay then begin
+ incr steps;
+ if !steps = 1000 then begin
+ Thread.delay 0.001;
+ steps := 0;
+ end
end
(** This function does not work on windows, sigh... *)
diff --git a/library/global.mli b/library/global.mli
index 2767594171..5faf0e8bbd 100644
--- a/library/global.mli
+++ b/library/global.mli
@@ -134,7 +134,7 @@ val body_of_constant_body : Opaqueproof.indirect_accessor ->
val start_library : DirPath.t -> ModPath.t
val export : ?except:Future.UUIDSet.t -> output_native_objects:bool -> DirPath.t ->
- ModPath.t * Safe_typing.compiled_library * Safe_typing.native_library
+ ModPath.t * Safe_typing.compiled_library * Nativelib.native_library
val import :
Safe_typing.compiled_library -> Univ.ContextSet.t -> Safe_typing.vodigest ->
ModPath.t
diff --git a/parsing/cLexer.ml b/parsing/cLexer.ml
index f485970eec..d8d2f2a2ef 100644
--- a/parsing/cLexer.ml
+++ b/parsing/cLexer.ml
@@ -823,7 +823,7 @@ let token_text : type c. c Tok.p -> string = function
| PKEYWORD t -> "'" ^ t ^ "'"
| PIDENT None -> "identifier"
| PIDENT (Some t) -> "'" ^ t ^ "'"
- | PNUMBER None -> "numeral"
+ | PNUMBER None -> "number"
| PNUMBER (Some n) -> "'" ^ NumTok.Unsigned.sprint n ^ "'"
| PSTRING None -> "string"
| PSTRING (Some s) -> "STRING \"" ^ s ^ "\""
@@ -916,7 +916,7 @@ let terminal s =
if is_ident_not_keyword s then PIDENT (Some s)
else PKEYWORD s
-(* Precondition: the input is a numeral (c.f. [NumTok.t]) *)
-let terminal_numeral s = match NumTok.Unsigned.parse_string s with
+(* Precondition: the input is a number (c.f. [NumTok.t]) *)
+let terminal_number s = match NumTok.Unsigned.parse_string s with
| Some n -> PNUMBER (Some n)
- | None -> failwith "numeral token expected."
+ | None -> failwith "number token expected."
diff --git a/parsing/cLexer.mli b/parsing/cLexer.mli
index ac2c5bcfe2..af4b7ba334 100644
--- a/parsing/cLexer.mli
+++ b/parsing/cLexer.mli
@@ -49,8 +49,8 @@ val check_keyword : string -> unit
(** When string is not an ident, returns a keyword. *)
val terminal : string -> string Tok.p
-(** Precondition: the input is a numeral (c.f. [NumTok.t]) *)
-val terminal_numeral : string -> NumTok.Unsigned.t Tok.p
+(** Precondition: the input is a number (c.f. [NumTok.t]) *)
+val terminal_number : string -> NumTok.Unsigned.t Tok.p
(** The lexer of Coq: *)
diff --git a/parsing/g_constr.mlg b/parsing/g_constr.mlg
index 349e14bba3..67a061175a 100644
--- a/parsing/g_constr.mlg
+++ b/parsing/g_constr.mlg
@@ -173,10 +173,10 @@ GRAMMAR EXTEND Gram
[ c = atomic_constr -> { c }
| c = term_match -> { c }
| "("; c = term LEVEL "200"; ")" ->
- { (* Preserve parentheses around numerals so that constrintern does not
- collapse -(3) into the numeral -3. *)
+ { (* Preserve parentheses around numbers so that constrintern does not
+ collapse -(3) into the number -3. *)
(match c.CAst.v with
- | CPrim (Numeral (NumTok.SPlus,n)) ->
+ | CPrim (Number (NumTok.SPlus,n)) ->
CAst.make ~loc @@ CNotation(None,(InConstrEntry,"( _ )"),([c],[],[],[]))
| _ -> c) }
| "{|"; c = record_declaration; bar_cbrace -> { c }
@@ -258,7 +258,7 @@ GRAMMAR EXTEND Gram
atomic_constr:
[ [ g = global; i = univ_annot -> { CAst.make ~loc @@ CRef (g,i) }
| s = sort -> { CAst.make ~loc @@ CSort s }
- | n = NUMBER-> { CAst.make ~loc @@ CPrim (Numeral (NumTok.SPlus,n)) }
+ | n = NUMBER-> { CAst.make ~loc @@ CPrim (Number (NumTok.SPlus,n)) }
| s = string -> { CAst.make ~loc @@ CPrim (String s) }
| "_" -> { CAst.make ~loc @@ CHole (None, IntroAnonymous, None) }
| "?"; "["; id = identref; "]" -> { CAst.make ~loc @@ CHole (None, IntroIdentifier id.CAst.v, None) }
@@ -362,15 +362,15 @@ GRAMMAR EXTEND Gram
| "{|"; pat = record_patterns; bar_cbrace -> { CAst.make ~loc @@ CPatRecord pat }
| "_" -> { CAst.make ~loc @@ CPatAtom None }
| "("; p = pattern LEVEL "200"; ")" ->
- { (* Preserve parentheses around numerals so that constrintern does not
- collapse -(3) into the numeral -3. *)
+ { (* Preserve parentheses around numbers so that constrintern does not
+ collapse -(3) into the number -3. *)
match p.CAst.v with
- | CPatPrim (Numeral (NumTok.SPlus,n)) ->
+ | CPatPrim (Number (NumTok.SPlus,n)) ->
CAst.make ~loc @@ CPatNotation(None,(InConstrEntry,"( _ )"),([p],[]),[])
| _ -> p }
| "("; p = pattern LEVEL "200"; "|" ; pl = LIST1 pattern LEVEL "200" SEP "|"; ")" ->
{ CAst.make ~loc @@ CPatOr (p::pl) }
- | n = NUMBER-> { CAst.make ~loc @@ CPatPrim (Numeral (NumTok.SPlus,n)) }
+ | n = NUMBER-> { CAst.make ~loc @@ CPatPrim (Number (NumTok.SPlus,n)) }
| s = string -> { CAst.make ~loc @@ CPatPrim (String s) } ] ]
;
fixannot:
diff --git a/plugins/firstorder/g_ground.mlg b/plugins/firstorder/g_ground.mlg
index 6ddc6ba21e..d6790d008a 100644
--- a/plugins/firstorder/g_ground.mlg
+++ b/plugins/firstorder/g_ground.mlg
@@ -108,10 +108,6 @@ let pr_firstorder_using_raw _ _ _ = Pptactic.pr_auto_using pr_qualid
let pr_firstorder_using_glob _ _ _ = Pptactic.pr_auto_using (Pputils.pr_or_var (fun x -> pr_global (snd x)))
let pr_firstorder_using_typed _ _ _ = Pptactic.pr_auto_using pr_global
-let warn_deprecated_syntax =
- CWarnings.create ~name:"firstorder-deprecated-syntax" ~category:"deprecated"
- (fun () -> Pp.strbrk "Deprecated syntax; use \",\" as separator")
-
}
ARGUMENT EXTEND firstorder_using
@@ -119,12 +115,7 @@ ARGUMENT EXTEND firstorder_using
PRINTED BY { pr_firstorder_using_typed }
RAW_PRINTED BY { pr_firstorder_using_raw }
GLOB_PRINTED BY { pr_firstorder_using_glob }
-| [ "using" reference(a) ] -> { [a] }
-| [ "using" reference(a) "," ne_reference_list_sep(l,",") ] -> { a::l }
-| [ "using" reference(a) reference(b) reference_list(l) ] -> {
- warn_deprecated_syntax ();
- a::b::l
- }
+| [ "using" ne_reference_list_sep(l,",") ] -> { l }
| [ ] -> { [] }
END
diff --git a/plugins/funind/indfun_common.ml b/plugins/funind/indfun_common.ml
index 0179215d6a..6464556e4e 100644
--- a/plugins/funind/indfun_common.ml
+++ b/plugins/funind/indfun_common.ml
@@ -108,7 +108,7 @@ let with_full_print f a =
Constrextern.print_universes := old_printuniverses;
Goptions.set_bool_option_value Detyping.print_allow_match_default_opt_name
old_printallowmatchdefaultclause;
- Dumpglob.continue ();
+ Dumpglob.pop_output ();
res
with reraise ->
Impargs.make_implicit_args old_implicit_args;
@@ -118,7 +118,7 @@ let with_full_print f a =
Constrextern.print_universes := old_printuniverses;
Goptions.set_bool_option_value Detyping.print_allow_match_default_opt_name
old_printallowmatchdefaultclause;
- Dumpglob.continue ();
+ Dumpglob.pop_output ();
raise reraise
(**********************)
diff --git a/plugins/ltac/g_ltac.mlg b/plugins/ltac/g_ltac.mlg
index c38a4dcd90..c2e95c45f9 100644
--- a/plugins/ltac/g_ltac.mlg
+++ b/plugins/ltac/g_ltac.mlg
@@ -329,11 +329,11 @@ GRAMMAR EXTEND Gram
;
command:
[ [ IDENT "Proof"; "with"; ta = Pltac.tactic;
- l = OPT [ "using"; l = G_vernac.section_subset_expr -> { l } ] ->
+ l = OPT [ IDENT "using"; l = G_vernac.section_subset_expr -> { l } ] ->
{ Vernacexpr.VernacProof (Some (in_tac ta), l) }
- | IDENT "Proof"; "using"; l = G_vernac.section_subset_expr;
- ta = OPT [ "with"; ta = Pltac.tactic -> { in_tac ta } ] ->
- { Vernacexpr.VernacProof (ta,Some l) } ] ]
+ | IDENT "Proof"; IDENT "using"; l = G_vernac.section_subset_expr;
+ "with"; ta = Pltac.tactic ->
+ { Vernacexpr.VernacProof (Some (in_tac ta),Some l) } ] ]
;
hint:
[ [ IDENT "Extern"; n = natural; c = OPT Constr.constr_pattern ; "=>";
@@ -466,7 +466,7 @@ END
VERNAC COMMAND EXTEND VernacPrintLtac CLASSIFIED AS QUERY
| [ "Print" "Ltac" reference(r) ] ->
- { Feedback.msg_notice (Tacintern.print_ltac r) }
+ { Feedback.msg_notice (Tacentries.print_ltac r) }
END
VERNAC COMMAND EXTEND VernacLocateLtac CLASSIFIED AS QUERY
diff --git a/plugins/ltac/g_rewrite.mlg b/plugins/ltac/g_rewrite.mlg
index ee94fd565a..a3f03b5bb5 100644
--- a/plugins/ltac/g_rewrite.mlg
+++ b/plugins/ltac/g_rewrite.mlg
@@ -67,12 +67,12 @@ END
{
type raw_strategy = (constr_expr, Tacexpr.raw_red_expr) strategy_ast
-type glob_strategy = (glob_constr_and_expr, Tacexpr.raw_red_expr) strategy_ast
+type glob_strategy = (glob_constr_and_expr, Tacexpr.glob_red_expr) strategy_ast
let interp_strategy ist gl s =
let sigma = project gl in
- sigma, strategy_of_ast s
-let glob_strategy ist s = map_strategy (Tacintern.intern_constr ist) (fun c -> c) s
+ sigma, strategy_of_ast ist s
+let glob_strategy ist s = map_strategy (Tacintern.intern_constr ist) (Tacintern.intern_red_expr ist) s
let subst_strategy s str = str
let pr_strategy _ _ _ (s : strategy) = Pp.str "<strategy>"
@@ -80,12 +80,9 @@ let pr_raw_strategy env sigma prc prlc _ (s : raw_strategy) =
let prr = Pptactic.pr_red_expr env sigma (prc, prlc, Pputils.pr_or_by_notation Libnames.pr_qualid, prc) in
Rewrite.pr_strategy (prc env sigma) prr s
let pr_glob_strategy env sigma prc prlc _ (s : glob_strategy) =
- let prr = Pptactic.pr_red_expr env sigma
- (Ppconstr.pr_constr_expr,
- Ppconstr.pr_lconstr_expr,
- Pputils.pr_or_by_notation Libnames.pr_qualid,
- Ppconstr.pr_constr_expr)
- in
+ let prpat env sigma (_,c,_) = prc env sigma c in
+ let prcst = Pputils.pr_or_var Pptactic.(pr_and_short_name (pr_evaluable_reference_env env)) in
+ let prr = Pptactic.pr_red_expr env sigma (prc, prlc, prcst, prpat) in
Rewrite.pr_strategy (prc env sigma) prr s
}
@@ -130,15 +127,15 @@ END
{
let db_strat db = StratUnary (Topdown, StratHints (false, db))
-let cl_rewrite_clause_db db = cl_rewrite_clause_strat (strategy_of_ast (db_strat db))
+let cl_rewrite_clause_db ist db = cl_rewrite_clause_strat (strategy_of_ast ist (db_strat db))
}
TACTIC EXTEND rewrite_strat
| [ "rewrite_strat" rewstrategy(s) "in" hyp(id) ] -> { cl_rewrite_clause_strat s (Some id) }
| [ "rewrite_strat" rewstrategy(s) ] -> { cl_rewrite_clause_strat s None }
-| [ "rewrite_db" preident(db) "in" hyp(id) ] -> { cl_rewrite_clause_db db (Some id) }
-| [ "rewrite_db" preident(db) ] -> { cl_rewrite_clause_db db None }
+| [ "rewrite_db" preident(db) "in" hyp(id) ] -> { cl_rewrite_clause_db ist db (Some id) }
+| [ "rewrite_db" preident(db) ] -> { cl_rewrite_clause_db ist db None }
END
{
diff --git a/plugins/ltac/g_tactic.mlg b/plugins/ltac/g_tactic.mlg
index 97d75261c5..ecfe6c1664 100644
--- a/plugins/ltac/g_tactic.mlg
+++ b/plugins/ltac/g_tactic.mlg
@@ -121,8 +121,8 @@ let destruction_arg_of_constr (c,lbind as clbind) = match lbind with
end
| _ -> ElimOnConstr clbind
-let mkNumeral n =
- Numeral (NumTok.Signed.of_int_string (string_of_int n))
+let mkNumber n =
+ Number (NumTok.Signed.of_int_string (string_of_int n))
let mkTacCase with_evar = function
| [(clear,ElimOnConstr cl),(None,None),None],None ->
@@ -130,7 +130,7 @@ let mkTacCase with_evar = function
(* Reinterpret numbers as a notation for terms *)
| [(clear,ElimOnAnonHyp n),(None,None),None],None ->
TacCase (with_evar,
- (clear,(CAst.make @@ CPrim (mkNumeral n),
+ (clear,(CAst.make @@ CPrim (mkNumber n),
NoBindings)))
(* Reinterpret ident as notations for variables in the context *)
(* because we don't know if they are quantified or not *)
diff --git a/plugins/ltac/pptactic.ml b/plugins/ltac/pptactic.ml
index 87da304330..edd56ee0f7 100644
--- a/plugins/ltac/pptactic.ml
+++ b/plugins/ltac/pptactic.ml
@@ -1135,8 +1135,8 @@ let pr_goal_selector ~toplevel s =
pr_dconstr = (fun env sigma -> pr_and_constr_expr (pr_glob_constr_env env));
pr_lconstr = (fun env sigma -> pr_and_constr_expr (pr_lglob_constr_env env));
pr_pattern = (fun env sigma -> pr_pat_and_constr_expr (pr_glob_constr_env env));
- pr_lpattern = (fun env sigma -> pr_pat_and_constr_expr (pr_lglob_constr_env env));
pr_constant = pr_or_var (pr_and_short_name (pr_evaluable_reference_env env));
+ pr_lpattern = (fun env sigma -> pr_pat_and_constr_expr (pr_lglob_constr_env env));
pr_reference = pr_ltac_or_var (pr_located pr_ltac_constant);
pr_name = pr_lident;
pr_generic = Pputils.pr_glb_generic;
diff --git a/plugins/ltac/rewrite.ml b/plugins/ltac/rewrite.ml
index a1970cbce2..26e2b18a02 100644
--- a/plugins/ltac/rewrite.ml
+++ b/plugins/ltac/rewrite.ml
@@ -1638,9 +1638,9 @@ let cl_rewrite_clause l left2right occs clause =
let cl_rewrite_clause_strat strat clause =
cl_rewrite_clause_strat false strat clause
-let apply_glob_constr c l2r occs = (); fun ({ state = () ; env = env } as input) ->
+let apply_glob_constr ist c l2r occs = (); fun ({ state = () ; env = env } as input) ->
let c sigma =
- let (sigma, c) = Pretyping.understand_tcc env sigma c in
+ let (sigma, c) = Tacinterp.interp_open_constr ist env sigma c in
(sigma, (c, NoBindings))
in
let flags = general_rewrite_unif_flags () in
@@ -1717,12 +1717,12 @@ let rec pr_strategy prc prr = function
| StratEval r -> str "eval" ++ spc () ++ prr r
| StratFold c -> str "fold" ++ spc () ++ prc c
-let rec strategy_of_ast = function
+let rec strategy_of_ast ist = function
| StratId -> Strategies.id
| StratFail -> Strategies.fail
| StratRefl -> Strategies.refl
| StratUnary (f, s) ->
- let s' = strategy_of_ast s in
+ let s' = strategy_of_ast ist s in
let f' = match f with
| Subterms -> all_subterms
| Subterm -> one_subterm
@@ -1736,13 +1736,13 @@ let rec strategy_of_ast = function
| Repeat -> Strategies.repeat
in f' s'
| StratBinary (f, s, t) ->
- let s' = strategy_of_ast s in
- let t' = strategy_of_ast t in
+ let s' = strategy_of_ast ist s in
+ let t' = strategy_of_ast ist t in
let f' = match f with
| Compose -> Strategies.seq
| Choice -> Strategies.choice
in f' s' t'
- | StratConstr (c, b) -> { strategy = apply_glob_constr (fst c) b AllOccurrences }
+ | StratConstr (c, b) -> { strategy = apply_glob_constr ist c b AllOccurrences }
| StratHints (old, id) -> if old then Strategies.old_hints id else Strategies.hints id
| StratTerms l -> { strategy =
(fun ({ state = () ; env } as input) ->
@@ -1751,7 +1751,7 @@ let rec strategy_of_ast = function
}
| StratEval r -> { strategy =
(fun ({ state = () ; env ; evars } as input) ->
- let (sigma,r_interp) = Tacinterp.interp_redexp env (goalevars evars) r in
+ let (sigma,r_interp) = Tacinterp.interp_red_expr ist env (goalevars evars) r in
(Strategies.reduce r_interp).strategy { input with
evars = (sigma,cstrevars evars) }) }
| StratFold c -> Strategies.fold_glob (fst c)
diff --git a/plugins/ltac/rewrite.mli b/plugins/ltac/rewrite.mli
index 60a66dd861..8e0ce183c2 100644
--- a/plugins/ltac/rewrite.mli
+++ b/plugins/ltac/rewrite.mli
@@ -62,7 +62,7 @@ type rewrite_result =
type strategy
-val strategy_of_ast : (glob_constr_and_expr, raw_red_expr) strategy_ast -> strategy
+val strategy_of_ast : interp_sign -> (glob_constr_and_expr, glob_red_expr) strategy_ast -> strategy
val map_strategy : ('a -> 'b) -> ('c -> 'd) ->
('a, 'c) strategy_ast -> ('b, 'd) strategy_ast
diff --git a/plugins/ltac/taccoerce.ml b/plugins/ltac/taccoerce.ml
index ee28229cb7..4c1fe6417e 100644
--- a/plugins/ltac/taccoerce.ml
+++ b/plugins/ltac/taccoerce.ml
@@ -394,8 +394,13 @@ type appl =
(* Values for interpretation *)
type tacvalue =
- | VFun of appl * Tacexpr.ltac_trace * Loc.t option * Val.t Id.Map.t *
- Name.t list * Tacexpr.glob_tactic_expr
+ | VFun of
+ appl *
+ Tacexpr.ltac_trace *
+ Loc.t option * (* when executing a global Ltac function: the location where this function was called *)
+ Val.t Id.Map.t * (* closure *)
+ Name.t list * (* binders *)
+ Tacexpr.glob_tactic_expr (* body *)
| VRec of Val.t Id.Map.t ref * Tacexpr.glob_tactic_expr
let (wit_tacvalue : (Empty.t, tacvalue, tacvalue) Genarg.genarg_type) =
diff --git a/plugins/ltac/tacentries.ml b/plugins/ltac/tacentries.ml
index a05b36c1b4..29e29044f1 100644
--- a/plugins/ltac/tacentries.ml
+++ b/plugins/ltac/tacentries.ml
@@ -528,16 +528,40 @@ let print_ltacs () =
let locatable_ltac = "Ltac"
+let split_ltac_fun = function
+ | Tacexpr.TacFun (l,t) -> (l,t)
+ | t -> ([],t)
+
+let pr_ltac_fun_arg n = spc () ++ Name.print n
+
+let print_ltac_body qid tac =
+ let filter mp =
+ try Some (Nametab.shortest_qualid_of_module mp)
+ with Not_found -> None
+ in
+ let mods = List.map_filter filter tac.Tacenv.tac_redef in
+ let redefined = match mods with
+ | [] -> mt ()
+ | mods ->
+ let redef = prlist_with_sep fnl pr_qualid mods in
+ fnl () ++ str "Redefined by:" ++ fnl () ++ redef
+ in
+ let l,t = split_ltac_fun tac.Tacenv.tac_body in
+ hv 2 (
+ hov 2 (str "Ltac" ++ spc() ++ pr_qualid qid ++
+ prlist pr_ltac_fun_arg l ++ spc () ++ str ":=")
+ ++ spc() ++ Pptactic.pr_glob_tactic (Global.env ()) t) ++ redefined
+
let () =
let open Prettyp in
- let locate qid = try Some (Tacenv.locate_tactic qid) with Not_found -> None in
- let locate_all = Tacenv.locate_extended_all_tactic in
- let shortest_qualid = Tacenv.shortest_qualid_of_tactic in
- let name kn = str "Ltac" ++ spc () ++ pr_path (Tacenv.path_of_tactic kn) in
- let print kn =
- let qid = qualid_of_path (Tacenv.path_of_tactic kn) in
- Tacintern.print_ltac qid
- in
+ let locate qid = try Some (qid, Tacenv.locate_tactic qid) with Not_found -> None in
+ let locate_all qid = List.map (fun kn -> (qid,kn)) (Tacenv.locate_extended_all_tactic qid) in
+ let shortest_qualid (qid,kn) = Tacenv.shortest_qualid_of_tactic kn in
+ let name (qid,kn) = str "Ltac" ++ spc () ++ pr_path (Tacenv.path_of_tactic kn) in
+ let print (qid,kn) =
+ let entries = Tacenv.ltac_entries () in
+ let tac = KNmap.find kn entries in
+ print_ltac_body qid tac in
let about = name in
register_locatable locatable_ltac {
locate;
@@ -551,6 +575,17 @@ let () =
let print_located_tactic qid =
Feedback.msg_notice (Prettyp.print_located_other locatable_ltac qid)
+let print_ltac id =
+ try
+ let kn = Tacenv.locate_tactic id in
+ let entries = Tacenv.ltac_entries () in
+ let tac = KNmap.find kn entries in
+ print_ltac_body id tac
+ with
+ Not_found ->
+ user_err ~hdr:"print_ltac"
+ (pr_qualid id ++ spc() ++ str "is not a user defined tactic.")
+
(** Grammar *)
let () =
diff --git a/plugins/ltac/tacentries.mli b/plugins/ltac/tacentries.mli
index 6ee3ce091b..fc9ab54eba 100644
--- a/plugins/ltac/tacentries.mli
+++ b/plugins/ltac/tacentries.mli
@@ -69,6 +69,9 @@ val print_ltacs : unit -> unit
val print_located_tactic : Libnames.qualid -> unit
(** Display the absolute name of a tactic. *)
+val print_ltac : Libnames.qualid -> Pp.t
+(** Display the definition of a tactic. *)
+
(** {5 Low-level registering of tactics} *)
type (_, 'a) ml_ty_sig =
diff --git a/plugins/ltac/tacintern.ml b/plugins/ltac/tacintern.ml
index 9c3b05fdf1..47f1d3bf66 100644
--- a/plugins/ltac/tacintern.ml
+++ b/plugins/ltac/tacintern.ml
@@ -769,38 +769,6 @@ let glob_tactic_env l env x =
(intern_pure_tactic { (Genintern.empty_glob_sign env) with ltacvars })
x
-let split_ltac_fun = function
- | TacFun (l,t) -> (l,t)
- | t -> ([],t)
-
-let pr_ltac_fun_arg n = spc () ++ Name.print n
-
-let print_ltac id =
- try
- let kn = Tacenv.locate_tactic id in
- let entries = Tacenv.ltac_entries () in
- let tac = KNmap.find kn entries in
- let filter mp =
- try Some (Nametab.shortest_qualid_of_module mp)
- with Not_found -> None
- in
- let mods = List.map_filter filter tac.Tacenv.tac_redef in
- let redefined = match mods with
- | [] -> mt ()
- | mods ->
- let redef = prlist_with_sep fnl pr_qualid mods in
- fnl () ++ str "Redefined by:" ++ fnl () ++ redef
- in
- let l,t = split_ltac_fun tac.Tacenv.tac_body in
- hv 2 (
- hov 2 (str "Ltac" ++ spc() ++ pr_qualid id ++
- prlist pr_ltac_fun_arg l ++ spc () ++ str ":=")
- ++ spc() ++ Pptactic.pr_glob_tactic (Global.env ()) t) ++ redefined
- with
- Not_found ->
- user_err ~hdr:"print_ltac"
- (pr_qualid id ++ spc() ++ str "is not a user defined tactic.")
-
(** Registering *)
let lift intern = (); fun ist x -> (ist, intern ist x)
diff --git a/plugins/ltac/tacintern.mli b/plugins/ltac/tacintern.mli
index 22ec15566b..f779aa470c 100644
--- a/plugins/ltac/tacintern.mli
+++ b/plugins/ltac/tacintern.mli
@@ -55,9 +55,6 @@ val intern_hyp : glob_sign -> lident -> lident
val intern_genarg : glob_sign -> raw_generic_argument -> glob_generic_argument
-(** printing *)
-val print_ltac : Libnames.qualid -> Pp.t
-
(** Reduction expressions *)
val intern_red_expr : glob_sign -> raw_red_expr -> glob_red_expr
diff --git a/plugins/ltac/tacinterp.ml b/plugins/ltac/tacinterp.ml
index 7728415ddd..3d734d3a66 100644
--- a/plugins/ltac/tacinterp.ml
+++ b/plugins/ltac/tacinterp.ml
@@ -153,11 +153,15 @@ let add_extra_loc loc extra =
match loc with
| None -> extra
| Some loc -> TacStore.set extra f_loc loc
-let add_loc loc ist =
+let extract_loc ist = TacStore.get ist.extra f_loc
+
+let ensure_loc loc ist =
match loc with
| None -> ist
- | Some loc -> { ist with extra = TacStore.set ist.extra f_loc loc }
-let extract_loc ist = TacStore.get ist.extra f_loc
+ | Some loc ->
+ match extract_loc ist with
+ | None -> { ist with extra = TacStore.set ist.extra f_loc loc }
+ | Some _ -> ist
let print_top_val env v = Pptactic.pr_value Pptactic.ltop v
@@ -1175,7 +1179,7 @@ and eval_tactic_ist ist tac : unit Proofview.tactic = match tac with
| TacFirst l -> Tacticals.New.tclFIRST (List.map (interp_tactic ist) l)
| TacSolve l -> Tacticals.New.tclSOLVE (List.map (interp_tactic ist) l)
| TacComplete tac -> Tacticals.New.tclCOMPLETE (interp_tactic ist tac)
- | TacArg {CAst.loc} -> Ftactic.run (val_interp (add_loc loc ist) tac) (fun v -> tactic_of_value ist v)
+ | TacArg {CAst.loc} -> Ftactic.run (val_interp (ensure_loc loc ist) tac) (fun v -> tactic_of_value ist v)
| TacSelect (sel, tac) -> Tacticals.New.tclSELECT sel (interp_tactic ist tac)
(* For extensions *)
| TacAlias {loc; v=(s,l)} ->
@@ -1254,9 +1258,12 @@ and interp_ltac_reference ?loc' mustbetac ist r : Val.t Ftactic.t =
let extra = TacStore.set extra f_trace trace in
let ist = { lfun = Id.Map.empty; poly; extra } in
let appl = GlbAppl[r,[]] in
+ (* We call a global ltac reference: add a loc on its executation only if not
+ already in another global reference *)
+ let ist = ensure_loc loc ist in
Profile_ltac.do_profile "interp_ltac_reference" trace ~count_call:false
- (catch_error_tac_loc (* interp *) loc false trace
- (val_interp ~appl (add_loc (* exec *) loc ist) (Tacenv.interp_ltac r)))
+ (catch_error_tac_loc (* loc for interpretation *) loc false trace
+ (val_interp ~appl ist (Tacenv.interp_ltac r)))
and interp_tacarg ist arg : Val.t Ftactic.t =
match arg with
@@ -1325,7 +1332,7 @@ and interp_app loc ist fv largs : Val.t Ftactic.t =
; extra = TacStore.set ist.extra f_trace []
} in
Profile_ltac.do_profile "interp_app" trace ~count_call:false
- (catch_error_tac_loc loc false trace (val_interp (add_loc loc ist) body)) >>= fun v ->
+ (catch_error_tac_loc loc false trace (val_interp (ensure_loc loc ist) body)) >>= fun v ->
Ftactic.return (name_vfun (push_appl appl largs) v)
end
begin fun (e, info) ->
diff --git a/plugins/ltac/tacinterp.mli b/plugins/ltac/tacinterp.mli
index fe3079198c..a74f4592f7 100644
--- a/plugins/ltac/tacinterp.mli
+++ b/plugins/ltac/tacinterp.mli
@@ -77,6 +77,9 @@ val val_interp : interp_sign -> glob_tactic_expr -> (value -> unit Proofview.tac
val interp_ltac_constr : interp_sign -> glob_tactic_expr -> (constr -> unit Proofview.tactic) -> unit Proofview.tactic
(** Interprets redexp arguments *)
+val interp_red_expr : interp_sign -> Environ.env -> Evd.evar_map -> glob_red_expr -> Evd.evar_map * red_expr
+
+(** Interprets redexp arguments from a raw one *)
val interp_redexp : Environ.env -> Evd.evar_map -> raw_red_expr -> Evd.evar_map * red_expr
(** Interprets tactic expressions *)
diff --git a/plugins/ssr/ssrparser.mlg b/plugins/ssr/ssrparser.mlg
index 35fecfb0a5..ccdf5fa68e 100644
--- a/plugins/ssr/ssrparser.mlg
+++ b/plugins/ssr/ssrparser.mlg
@@ -350,7 +350,7 @@ 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 (None, []) with
- | Constrexpr.Numeral n, _ when NumTok.Signed.is_int n ->
+ | Constrexpr.Number n, _ when NumTok.Signed.is_int n ->
int_of_string (NumTok.Signed.to_string n)
| _ -> raise Not_found
end
diff --git a/plugins/ssr/ssrvernac.mlg b/plugins/ssr/ssrvernac.mlg
index a49a5e8b28..99cf197b78 100644
--- a/plugins/ssr/ssrvernac.mlg
+++ b/plugins/ssr/ssrvernac.mlg
@@ -304,21 +304,6 @@ END
{
- let warn_search_moved_enabled = ref true
- let warn_search_moved = CWarnings.create ~name:"ssr-search-moved"
- ~category:"deprecated" ~default:CWarnings.Enabled
- (fun () ->
- (Pp.strbrk
- "In previous versions of Coq, loading SSReflect had the effect of \
- replacing the built-in 'Search' command with an SSReflect version \
- of that command. \
- Coq's own search feature was still available via 'SearchAbout' \
- (but that alias is deprecated). \
- This replacement no longer happens; now 'Search' calls Coq's own search \
- feature even when SSReflect is loaded. \
- If you want to use SSReflect's deprecated Search command \
- instead of the built-in one, please Require the ssrsearch module."))
-
open G_vernac
}
@@ -328,7 +313,6 @@ GRAMMAR EXTEND Gram
query_command:
[ [ IDENT "Search"; s = search_query; l = search_queries; "." ->
{ let (sl,m) = l in
- if !warn_search_moved_enabled then warn_search_moved ();
fun g ->
Vernacexpr.VernacSearch (Vernacexpr.Search (s::sl),g, m) }
] ]
diff --git a/plugins/ssr/ssrvernac.mli b/plugins/ssr/ssrvernac.mli
index 93339313f0..327a2d4660 100644
--- a/plugins/ssr/ssrvernac.mli
+++ b/plugins/ssr/ssrvernac.mli
@@ -9,5 +9,3 @@
(************************************************************************)
(* This file is (C) Copyright 2006-2015 Microsoft Corporation and Inria. *)
-
-val warn_search_moved_enabled : bool ref
diff --git a/plugins/ssrsearch/g_search.mlg b/plugins/ssrsearch/g_search.mlg
index 5e002e09cc..54fdea0860 100644
--- a/plugins/ssrsearch/g_search.mlg
+++ b/plugins/ssrsearch/g_search.mlg
@@ -301,10 +301,6 @@ let ssrdisplaysearch gr env t =
let pr_res = pr_global gr ++ str ":" ++ spc () ++ pr_lconstr_env env Evd.empty t in
Feedback.msg_notice (hov 2 pr_res ++ fnl ())
-(* Remove the warning entirely when this plugin is loaded. *)
-let _ =
- Ssreflect_plugin.Ssrvernac.warn_search_moved_enabled := false
-
let deprecated_search =
CWarnings.create
~name:"deprecated-ssr-search"
diff --git a/plugins/syntax/dune b/plugins/syntax/dune
index b395695c8a..f930fc265a 100644
--- a/plugins/syntax/dune
+++ b/plugins/syntax/dune
@@ -1,22 +1,8 @@
(library
- (name numeral_notation_plugin)
- (public_name coq.plugins.numeral_notation)
- (synopsis "Coq numeral notation plugin")
- (modules g_numeral numeral)
- (libraries coq.vernac))
-
-(library
- (name string_notation_plugin)
- (public_name coq.plugins.string_notation)
- (synopsis "Coq string notation plugin")
- (modules g_string string_notation)
- (libraries coq.vernac))
-
-(library
- (name r_syntax_plugin)
- (public_name coq.plugins.r_syntax)
- (synopsis "Coq syntax plugin: reals")
- (modules r_syntax)
+ (name number_string_notation_plugin)
+ (public_name coq.plugins.number_string_notation)
+ (synopsis "Coq number and string notation plugin")
+ (modules g_number_string string_notation number)
(libraries coq.vernac))
(library
@@ -33,4 +19,4 @@
(modules float_syntax)
(libraries coq.vernac))
-(coq.pp (modules g_numeral g_string))
+(coq.pp (modules g_number_string))
diff --git a/plugins/syntax/g_number_string.mlg b/plugins/syntax/g_number_string.mlg
new file mode 100644
index 0000000000..c8badd238d
--- /dev/null
+++ b/plugins/syntax/g_number_string.mlg
@@ -0,0 +1,110 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+DECLARE PLUGIN "number_string_notation_plugin"
+
+{
+
+open Notation
+open Number
+open String_notation
+open Pp
+open Names
+open Stdarg
+open Pcoq.Prim
+
+let pr_number_after = function
+ | Nop -> mt ()
+ | Warning n -> str "warning after " ++ NumTok.UnsignedNat.print n
+ | Abstract n -> str "abstract after " ++ NumTok.UnsignedNat.print n
+
+let pr_deprecated_number_modifier m = str "(" ++ pr_number_after m ++ str ")"
+
+let warn_deprecated_numeral_notation =
+ CWarnings.create ~name:"numeral-notation" ~category:"deprecated"
+ (fun () ->
+ strbrk "Numeral Notation is deprecated, please use Number Notation instead.")
+
+let pr_number_string_mapping (b, n, n') =
+ if b then
+ str "[" ++ Libnames.pr_qualid n ++ str "]" ++ spc () ++ str "=>" ++ spc ()
+ ++ Libnames.pr_qualid n'
+ else
+ Libnames.pr_qualid n ++ spc () ++ str "=>" ++ spc ()
+ ++ Libnames.pr_qualid n'
+
+let pr_number_string_via (n, l) =
+ str "via " ++ Libnames.pr_qualid n ++ str " mapping ["
+ ++ prlist_with_sep pr_comma pr_number_string_mapping l ++ str "]"
+
+let pr_number_modifier = function
+ | After a -> pr_number_after a
+ | Via nl -> pr_number_string_via nl
+
+let pr_number_options l =
+ str "(" ++ prlist_with_sep pr_comma pr_number_modifier l ++ str ")"
+
+let pr_string_option l =
+ str "(" ++ pr_number_string_via l ++ str ")"
+
+}
+
+VERNAC ARGUMENT EXTEND deprecated_number_modifier
+ PRINTED BY { pr_deprecated_number_modifier }
+| [ ] -> { Nop }
+| [ "(" "warning" "after" bignat(waft) ")" ] -> { Warning (NumTok.UnsignedNat.of_string waft) }
+| [ "(" "abstract" "after" bignat(n) ")" ] -> { Abstract (NumTok.UnsignedNat.of_string n) }
+END
+
+VERNAC ARGUMENT EXTEND number_string_mapping
+ PRINTED BY { pr_number_string_mapping }
+| [ reference(n) "=>" reference(n') ] -> { false, n, n' }
+| [ "[" reference(n) "]" "=>" reference(n') ] -> { true, n, n' }
+END
+
+VERNAC ARGUMENT EXTEND number_string_via
+ PRINTED BY { pr_number_string_via }
+| [ "via" reference(n) "mapping" "[" ne_number_string_mapping_list_sep(l, ",") "]" ] -> { n, l }
+END
+
+VERNAC ARGUMENT EXTEND number_modifier
+ PRINTED BY { pr_number_modifier }
+| [ "warning" "after" bignat(waft) ] -> { After (Warning (NumTok.UnsignedNat.of_string waft)) }
+| [ "abstract" "after" bignat(n) ] -> { After (Abstract (NumTok.UnsignedNat.of_string n)) }
+| [ number_string_via(v) ] -> { Via v }
+END
+
+VERNAC ARGUMENT EXTEND number_options
+ PRINTED BY { pr_number_options }
+| [ "(" ne_number_modifier_list_sep(l, ",") ")" ] -> { l }
+END
+
+VERNAC ARGUMENT EXTEND string_option
+ PRINTED BY { pr_string_option }
+| [ "(" number_string_via(v) ")" ] -> { v }
+END
+
+VERNAC COMMAND EXTEND NumberNotation CLASSIFIED AS SIDEFF
+ | #[ locality = Attributes.locality; ] [ "Number" "Notation" reference(ty) reference(f) reference(g) number_options_opt(nl) ":"
+ ident(sc) ] ->
+
+ { vernac_number_notation (Locality.make_module_locality locality) ty f g (Option.default [] nl) (Id.to_string sc) }
+ | #[ locality = Attributes.locality; ] [ "Numeral" "Notation" reference(ty) reference(f) reference(g) ":"
+ ident(sc) deprecated_number_modifier(o) ] ->
+
+ { warn_deprecated_numeral_notation ();
+ vernac_number_notation (Locality.make_module_locality locality) ty f g [After o] (Id.to_string sc) }
+END
+
+VERNAC COMMAND EXTEND StringNotation CLASSIFIED AS SIDEFF
+ | #[ locality = Attributes.locality; ] [ "String" "Notation" reference(ty) reference(f) reference(g) string_option_opt(o) ":"
+ ident(sc) ] ->
+ { vernac_string_notation (Locality.make_module_locality locality) ty f g o (Id.to_string sc) }
+END
diff --git a/plugins/syntax/g_numeral.mlg b/plugins/syntax/g_numeral.mlg
deleted file mode 100644
index 93d91abea3..0000000000
--- a/plugins/syntax/g_numeral.mlg
+++ /dev/null
@@ -1,51 +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) *)
-(************************************************************************)
-
-DECLARE PLUGIN "numeral_notation_plugin"
-
-{
-
-open Notation
-open Numeral
-open Pp
-open Names
-open Stdarg
-open Pcoq.Prim
-
-let pr_numnot_option = function
- | Nop -> mt ()
- | Warning n -> str "(warning after " ++ NumTok.UnsignedNat.print n ++ str ")"
- | Abstract n -> str "(abstract after " ++ NumTok.UnsignedNat.print n ++ str ")"
-
-let warn_deprecated_numeral_notation =
- CWarnings.create ~name:"numeral-notation" ~category:"deprecated"
- (fun () ->
- strbrk "Numeral Notation is deprecated, please use Number Notation instead.")
-
-}
-
-VERNAC ARGUMENT EXTEND numeral_modifier
- PRINTED BY { pr_numnot_option }
-| [ ] -> { Nop }
-| [ "(" "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
- | #[ locality = Attributes.locality; ] [ "Number" "Notation" reference(ty) reference(f) reference(g) ":"
- ident(sc) numeral_modifier(o) ] ->
-
- { vernac_numeral_notation (Locality.make_module_locality locality) ty f g (Id.to_string sc) o }
- | #[ locality = Attributes.locality; ] [ "Numeral" "Notation" reference(ty) reference(f) reference(g) ":"
- ident(sc) numeral_modifier(o) ] ->
-
- { warn_deprecated_numeral_notation ();
- vernac_numeral_notation (Locality.make_module_locality locality) ty f g (Id.to_string sc) o }
-END
diff --git a/plugins/syntax/g_string.mlg b/plugins/syntax/g_string.mlg
deleted file mode 100644
index 788f9e011d..0000000000
--- a/plugins/syntax/g_string.mlg
+++ /dev/null
@@ -1,25 +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) *)
-(************************************************************************)
-
-DECLARE PLUGIN "string_notation_plugin"
-
-{
-
-open String_notation
-open Names
-open Stdarg
-
-}
-
-VERNAC COMMAND EXTEND StringNotation CLASSIFIED AS SIDEFF
- | #[ locality = Attributes.locality; ] [ "String" "Notation" reference(ty) reference(f) reference(g) ":"
- ident(sc) ] ->
- { vernac_string_notation (Locality.make_module_locality locality) ty f g (Id.to_string sc) }
-END
diff --git a/plugins/syntax/int63_syntax.ml b/plugins/syntax/int63_syntax.ml
index 5f4db8e800..b14b02f3bb 100644
--- a/plugins/syntax/int63_syntax.ml
+++ b/plugins/syntax/int63_syntax.ml
@@ -43,6 +43,7 @@ let _ =
let id_int63 = Nametab.locate q_id_int63 in
let o = { to_kind = Int63, Direct;
to_ty = id_int63;
+ to_post = [||];
of_kind = Int63, Direct;
of_ty = id_int63;
ty_name = q_int63;
@@ -50,7 +51,7 @@ let _ =
enable_prim_token_interpretation
{ pt_local = false;
pt_scope = int63_scope;
- pt_interp_info = NumeralNotation o;
+ pt_interp_info = NumberNotation o;
pt_required = (int63_path, int63_module);
pt_refs = [];
pt_in_match = false })
diff --git a/plugins/syntax/number.ml b/plugins/syntax/number.ml
new file mode 100644
index 0000000000..89d757a72a
--- /dev/null
+++ b/plugins/syntax/number.ml
@@ -0,0 +1,505 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+open Pp
+open Util
+open Names
+open Libnames
+open Constrexpr
+open Constrexpr_ops
+open Notation
+
+module CSet = CSet.Make (Constr)
+module CMap = CMap.Make (Constr)
+
+(** * Number notation *)
+
+type number_string_via = qualid * (bool * qualid * qualid) list
+type number_option =
+ | After of numnot_option
+ | Via of number_string_via
+
+let warn_abstract_large_num_no_op =
+ CWarnings.create ~name:"abstract-large-number-no-op" ~category:"numbers"
+ (fun f ->
+ strbrk "The 'abstract after' directive has no effect when " ++
+ strbrk "the parsing function (" ++
+ Nametab.pr_global_env (Termops.vars_of_env (Global.env ())) f ++ strbrk ") targets an " ++
+ strbrk "option type.")
+
+let get_constructors ind =
+ let mib,oib = Global.lookup_inductive ind in
+ let mc = oib.Declarations.mind_consnames in
+ Array.to_list
+ (Array.mapi (fun j c -> GlobRef.ConstructRef (ind, j + 1)) mc)
+
+let qualid_of_ref n =
+ n |> Coqlib.lib_ref |> Nametab.shortest_qualid_of_global Id.Set.empty
+
+let q_option () = qualid_of_ref "core.option.type"
+
+let unsafe_locate_ind q =
+ match Nametab.locate q with
+ | GlobRef.IndRef i -> i
+ | _ -> raise Not_found
+
+let locate_z () =
+ let zn = "num.Z.type" in
+ let pn = "num.pos.type" in
+ if Coqlib.has_ref zn && Coqlib.has_ref pn
+ then
+ let q_z = qualid_of_ref zn in
+ let q_pos = qualid_of_ref pn in
+ Some ({
+ z_ty = unsafe_locate_ind q_z;
+ pos_ty = unsafe_locate_ind q_pos;
+ }, mkRefC q_z)
+ else None
+
+let locate_number () =
+ let dint = "num.int.type" in
+ let duint = "num.uint.type" in
+ let dec = "num.decimal.type" in
+ let hint = "num.hexadecimal_int.type" in
+ let huint = "num.hexadecimal_uint.type" in
+ let hex = "num.hexadecimal.type" in
+ let int = "num.num_int.type" in
+ let uint = "num.num_uint.type" in
+ let num = "num.number.type" in
+ if Coqlib.has_ref dint && Coqlib.has_ref duint && Coqlib.has_ref dec
+ && Coqlib.has_ref hint && Coqlib.has_ref huint && Coqlib.has_ref hex
+ && Coqlib.has_ref int && Coqlib.has_ref uint && Coqlib.has_ref num
+ then
+ let q_dint = qualid_of_ref dint in
+ let q_duint = qualid_of_ref duint in
+ let q_dec = qualid_of_ref dec in
+ let q_hint = qualid_of_ref hint in
+ let q_huint = qualid_of_ref huint in
+ let q_hex = qualid_of_ref hex in
+ let q_int = qualid_of_ref int in
+ let q_uint = qualid_of_ref uint in
+ let q_num = qualid_of_ref num in
+ let int_ty = {
+ dec_int = unsafe_locate_ind q_dint;
+ dec_uint = unsafe_locate_ind q_duint;
+ hex_int = unsafe_locate_ind q_hint;
+ hex_uint = unsafe_locate_ind q_huint;
+ int = unsafe_locate_ind q_int;
+ uint = unsafe_locate_ind q_uint;
+ } in
+ let num_ty = {
+ int = int_ty;
+ decimal = unsafe_locate_ind q_dec;
+ hexadecimal = unsafe_locate_ind q_hex;
+ number = unsafe_locate_ind q_num;
+ } in
+ Some (int_ty, mkRefC q_int, mkRefC q_uint, mkRefC q_dint, mkRefC q_duint,
+ num_ty, mkRefC q_num, mkRefC q_dec)
+ else None
+
+let locate_int63 () =
+ let int63n = "num.int63.type" in
+ if Coqlib.has_ref int63n
+ then
+ let q_int63 = qualid_of_ref int63n in
+ Some (mkRefC q_int63)
+ else None
+
+let has_type env sigma f ty =
+ let c = mkCastC (mkRefC f, Glob_term.CastConv ty) in
+ try let _ = Constrintern.interp_constr env sigma c in true
+ with Pretype_errors.PretypeError _ -> false
+
+let type_error_to f ty =
+ CErrors.user_err
+ (pr_qualid f ++ str " should go from Number.int to " ++
+ pr_qualid ty ++ str " or (option " ++ pr_qualid ty ++ str ")." ++
+ fnl () ++ str "Instead of Number.int, the types Number.uint or Z or Int63.int or Number.number could be used (you may need to require BinNums or Number or Int63 first).")
+
+let type_error_of g ty =
+ CErrors.user_err
+ (pr_qualid g ++ str " should go from " ++ pr_qualid ty ++
+ str " to Number.int or (option Number.int)." ++ fnl () ++
+ str "Instead of Number.int, the types Number.uint or Z or Int63.int or Number.number could be used (you may need to require BinNums or Number or Int63 first).")
+
+let warn_deprecated_decimal =
+ CWarnings.create ~name:"decimal-numeral-notation" ~category:"deprecated"
+ (fun () ->
+ strbrk "Deprecated Number Notation for Decimal.uint, \
+ Decimal.int or Decimal.decimal. Use Number.uint, \
+ Number.int or Number.number respectively.")
+
+let error_params ind =
+ CErrors.user_err
+ (str "Wrong number of parameters for inductive" ++ spc ()
+ ++ Printer.pr_global (GlobRef.IndRef ind) ++ str ".")
+
+let remapping_error ?loc ty ty' ty'' =
+ CErrors.user_err ?loc
+ (Printer.pr_global ty
+ ++ str " was already mapped to" ++ spc () ++ Printer.pr_global ty'
+ ++ str " and cannot be remapped to" ++ spc () ++ Printer.pr_global ty''
+ ++ str ".")
+
+let error_missing c =
+ CErrors.user_err
+ (str "Missing mapping for constructor " ++ Printer.pr_global c ++ str ".")
+
+let pr_constr env sigma c =
+ let c = Constrextern.extern_constr env sigma (EConstr.of_constr c) in
+ Ppconstr.pr_constr_expr env sigma c
+
+let warn_via_remapping =
+ CWarnings.create ~name:"via-type-remapping" ~category:"numbers"
+ (fun (env, sigma, ty, ty', ty'') ->
+ let constr = pr_constr env sigma in
+ constr ty ++ str " was already mapped to" ++ spc () ++ constr ty'
+ ++ str ", mapping it also to" ++ spc () ++ constr ty''
+ ++ str " might yield ill typed terms when using the notation.")
+
+let warn_via_type_mismatch =
+ CWarnings.create ~name:"via-type-mismatch" ~category:"numbers"
+ (fun (env, sigma, g, g', exp, actual) ->
+ let constr = pr_constr env sigma in
+ str "Type of" ++ spc() ++ Printer.pr_global g
+ ++ str " seems incompatible with the type of" ++ spc ()
+ ++ Printer.pr_global g' ++ str "." ++ spc ()
+ ++ str "Expected type is: " ++ constr exp ++ spc ()
+ ++ str "instead of " ++ constr actual ++ str "." ++ spc ()
+ ++ str "This might yield ill typed terms when using the notation.")
+
+let multiple_via_error () =
+ CErrors.user_err (Pp.str "Multiple 'via' options.")
+
+let multiple_after_error () =
+ CErrors.user_err (Pp.str "Multiple 'warning after' or 'abstract after' options.")
+
+let via_abstract_error () =
+ CErrors.user_err (Pp.str "'via' and 'abstract' cannot be used together.")
+
+let locate_global_sort_inductive_or_constant sigma qid =
+ let locate_sort qid =
+ match Nametab.locate_extended qid with
+ | Globnames.TrueGlobal _ -> raise Not_found
+ | Globnames.SynDef kn ->
+ match Syntax_def.search_syntactic_definition kn with
+ | [], Notation_term.NSort r ->
+ let sigma,c = Evd.fresh_sort_in_family sigma (Glob_ops.glob_sort_family r) in
+ sigma,Constr.mkSort c
+ | _ -> raise Not_found in
+ try locate_sort qid
+ with Not_found ->
+ match Smartlocate.global_with_alias qid with
+ | GlobRef.IndRef i -> sigma, Constr.mkInd i
+ | _ -> sigma, Constr.mkConst (Smartlocate.global_constant_with_alias qid)
+
+let locate_global_constructor_inductive_or_constant qid =
+ let g = Smartlocate.global_with_alias qid in
+ match g with
+ | GlobRef.ConstructRef c -> g, Constr.mkConstruct c
+ | GlobRef.IndRef i -> g, Constr.mkInd i
+ | _ -> g, Constr.mkConst (Smartlocate.global_constant_with_alias qid)
+
+(* [get_type env sigma c] retrieves the type of [c] and returns a pair
+ [l, t] such that [c : l_0 -> ... -> l_n -> t]. *)
+let get_type env sigma c =
+ (* inspired from [compute_implicit_names] in "interp/impargs.ml" *)
+ let rec aux env acc t =
+ let t = Reductionops.whd_all env sigma t in
+ match EConstr.kind sigma t with
+ | Constr.Prod (na, a, b) ->
+ let a = Reductionops.whd_all env sigma a in
+ let rel = Context.Rel.Declaration.LocalAssum (na, a) in
+ aux (EConstr.push_rel rel env) ((na, a) :: acc) b
+ | _ -> List.rev acc, t in
+ let t = Retyping.get_type_of env sigma (EConstr.of_constr c) in
+ let l, t = aux env [] t in
+ List.map (fun (na, a) -> na, EConstr.Unsafe.to_constr a) l,
+ EConstr.Unsafe.to_constr t
+
+(* [elaborate_to_post_params env sigma ty_ind params] builds the
+ [to_post] translation (c.f., interp/notation.mli) for the numeral
+ notation to parse/print type [ty_ind]. This translation is the
+ identity ([ToPostCopy]) except that it checks ([ToPostCheck]) that
+ the parameters of the inductive type [ty_ind] match the ones given
+ in [params]. *)
+let elaborate_to_post_params env sigma ty_ind params =
+ let to_post_for_constructor indc =
+ let sigma, c = match indc with
+ | GlobRef.ConstructRef c ->
+ let sigma,c = Evd.fresh_constructor_instance env sigma c in
+ sigma, Constr.mkConstructU c
+ | _ -> assert false in (* c.f. get_constructors *)
+ let args, t = get_type env sigma c in
+ let params_indc = match Constr.kind t with
+ | Constr.App (_, a) -> Array.to_list a | _ -> [] in
+ let sz = List.length args in
+ let a = Array.make sz ToPostCopy in
+ if List.length params <> List.length params_indc then error_params ty_ind;
+ List.iter2 (fun param param_indc ->
+ match param, Constr.kind param_indc with
+ | Some p, Constr.Rel i when i <= sz -> a.(sz - i) <- ToPostCheck p
+ | _ -> ())
+ params params_indc;
+ indc, indc, Array.to_list a in
+ let pt_refs = get_constructors ty_ind in
+ let to_post_0 = List.map to_post_for_constructor pt_refs in
+ let to_post =
+ let only_copy (_, _, args) = List.for_all ((=) ToPostCopy) args in
+ if (List.for_all only_copy to_post_0) then [||] else [|to_post_0|] in
+ to_post, pt_refs
+
+(* [elaborate_to_post_via env sigma ty_name ty_ind l] builds the [to_post]
+ translation (c.f., interp/notation.mli) for the number notation to
+ parse/print type [ty_name] through the inductive [ty_ind] according
+ to the pairs [constant, constructor] in the list [l]. *)
+let elaborate_to_post_via env sigma ty_name ty_ind l =
+ let sigma, ty_name =
+ locate_global_sort_inductive_or_constant sigma ty_name in
+ let ty_ind = Constr.mkInd ty_ind in
+ (* Retrieve constants and constructors mappings and their type.
+ For each constant [cnst] and inductive constructor [indc] in [l], retrieve:
+ * its location: [lcnst] and [lindc]
+ * its GlobRef: [cnst] and [indc]
+ * its type: [tcnst] and [tindc] (decomposed in product by [get_type] above)
+ * [impls] are the implicit arguments of [cnst] *)
+ let l =
+ let read (consider_implicits, cnst, indc) =
+ let lcnst, lindc = cnst.CAst.loc, indc.CAst.loc in
+ let cnst, ccnst = locate_global_constructor_inductive_or_constant cnst in
+ let indc, cindc =
+ let indc = Smartlocate.global_constructor_with_alias indc in
+ GlobRef.ConstructRef indc, Constr.mkConstruct indc in
+ let get_type_wo_params c =
+ (* ignore parameters of inductive types *)
+ let rm_params c = match Constr.kind c with
+ | Constr.App (c, _) when Constr.isInd c -> c
+ | _ -> c in
+ let lc, tc = get_type env sigma c in
+ List.map (fun (n, c) -> n, rm_params c) lc, rm_params tc in
+ let tcnst, tindc = get_type_wo_params ccnst, get_type_wo_params cindc in
+ let impls =
+ if not consider_implicits then [] else
+ Impargs.(select_stronger_impargs (implicits_of_global cnst)) in
+ lcnst, cnst, tcnst, lindc, indc, tindc, impls in
+ List.map read l in
+ let eq_indc indc (_, _, _, _, indc', _, _) = GlobRef.equal indc indc' in
+ (* Collect all inductive types involved.
+ That is [ty_ind] and all final codomains of [tindc] above. *)
+ let inds =
+ List.fold_left (fun s (_, _, _, _, _, tindc, _) -> CSet.add (snd tindc) s)
+ (CSet.singleton ty_ind) l in
+ (* And for each inductive, retrieve its constructors. *)
+ let constructors =
+ CSet.fold (fun ind m ->
+ let inductive, _ = Constr.destInd ind in
+ CMap.add ind (get_constructors inductive) m)
+ inds CMap.empty in
+ (* Error if one [constructor] in some inductive in [inds]
+ doesn't appear exactly once in [l] *)
+ let _ = (* check_for duplicate constructor and error *)
+ List.fold_left (fun already_seen (_, cnst, _, loc, indc, _, _) ->
+ try
+ let cnst' = List.assoc_f GlobRef.equal indc already_seen in
+ remapping_error ?loc indc cnst' cnst
+ with Not_found -> (indc, cnst) :: already_seen)
+ [] l in
+ let () = (* check for missing constructor and error *)
+ CMap.iter (fun _ ->
+ List.iter (fun cstr ->
+ if not (List.exists (eq_indc cstr) l) then error_missing cstr))
+ constructors in
+ (* Perform some checks on types and warn if they look strange.
+ These checks are neither sound nor complete, so we only warn. *)
+ let () =
+ (* associate inductives to types, and check that this mapping is one to one
+ and maps [ty_ind] to [ty_name] *)
+ let ind2ty, ty2ind =
+ let add loc ckey cval m =
+ match CMap.find_opt ckey m with
+ | None -> CMap.add ckey cval m
+ | Some old_cval ->
+ if not (Constr.equal old_cval cval) then
+ warn_via_remapping ?loc (env, sigma, ckey, old_cval, cval);
+ m in
+ List.fold_left
+ (fun (ind2ty, ty2ind) (lcnst, _, (_, tcnst), lindc, _, (_, tindc), _) ->
+ add lcnst tindc tcnst ind2ty, add lindc tcnst tindc ty2ind)
+ CMap.(singleton ty_ind ty_name, singleton ty_name ty_ind) l in
+ (* check that type of constants and constructors mapped in [l]
+ match modulo [ind2ty] *)
+ let rm_impls impls (l, t) =
+ let rec aux impls l = match impls, l with
+ | Some _ :: impls, _ :: b -> aux impls b
+ | None :: impls, (n, a) :: b -> (n, a) :: aux impls b
+ | _ -> l in
+ aux impls l, t in
+ let replace m (l, t) =
+ let apply_m c = try CMap.find c m with Not_found -> c in
+ List.fold_right (fun (na, a) b -> Constr.mkProd (na, (apply_m a), b))
+ l (apply_m t) in
+ List.iter (fun (_, cnst, tcnst, loc, indc, tindc, impls) ->
+ let tcnst = rm_impls impls tcnst in
+ let tcnst' = replace CMap.empty tcnst in
+ if not (Constr.equal tcnst' (replace ind2ty tindc)) then
+ let actual = replace CMap.empty tindc in
+ let expected = replace ty2ind tcnst in
+ warn_via_type_mismatch ?loc (env, sigma, indc, cnst, expected, actual))
+ l in
+ (* Associate an index to each inductive, starting from 0 for [ty_ind]. *)
+ let ind2num, num2ind, nb_ind =
+ CMap.fold (fun ind _ (ind2num, num2ind, i) ->
+ CMap.add ind i ind2num, Int.Map.add i ind num2ind, i + 1)
+ (CMap.remove ty_ind constructors)
+ (CMap.singleton ty_ind 0, Int.Map.singleton 0 ty_ind, 1) in
+ (* Finally elaborate [to_post] *)
+ let to_post =
+ let rec map_prod impls tindc = match impls with
+ | Some _ :: impls -> ToPostHole :: map_prod impls tindc
+ | _ ->
+ match tindc with
+ | [] -> []
+ | (_, a) :: b ->
+ let t = match CMap.find_opt a ind2num with
+ | Some i -> ToPostAs i
+ | None -> ToPostCopy in
+ let impls = match impls with [] -> [] | _ :: t -> t in
+ t :: map_prod impls b in
+ Array.init nb_ind (fun i ->
+ List.map (fun indc ->
+ let _, cnst, _, _, _, tindc, impls = List.find (eq_indc indc) l in
+ indc, cnst, map_prod impls (fst tindc))
+ (CMap.find (Int.Map.find i num2ind) constructors)) in
+ (* and use constants mapped to constructors of [ty_ind] as triggers. *)
+ let pt_refs = List.map (fun (_, cnst, _) -> cnst) (to_post.(0)) in
+ to_post, pt_refs
+
+let locate_global_inductive allow_params qid =
+ let locate_param_inductive qid =
+ match Nametab.locate_extended qid with
+ | Globnames.TrueGlobal _ -> raise Not_found
+ | Globnames.SynDef kn ->
+ match Syntax_def.search_syntactic_definition kn with
+ | [], Notation_term.(NApp (NRef (GlobRef.IndRef i), l)) when allow_params ->
+ i,
+ List.map (function
+ | Notation_term.NRef r -> Some r
+ | Notation_term.NHole _ -> None
+ | _ -> raise Not_found) l
+ | _ -> raise Not_found in
+ try locate_param_inductive qid
+ with Not_found -> Smartlocate.global_inductive_with_alias qid, []
+
+let vernac_number_notation local ty f g opts scope =
+ let rec parse_opts = function
+ | [] -> None, Nop
+ | h :: opts ->
+ let via, opts = parse_opts opts in
+ let via = match h, via with
+ | Via _, Some _ -> multiple_via_error ()
+ | Via v, None -> Some v
+ | _ -> via in
+ let opts = match h, opts with
+ | After _, (Warning _ | Abstract _) -> multiple_after_error ()
+ | After a, Nop -> a
+ | _ -> opts in
+ via, opts in
+ let via, opts = parse_opts opts in
+ (match via, opts with Some _, Abstract _ -> via_abstract_error () | _ -> ());
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ let num_ty = locate_number () in
+ let z_pos_ty = locate_z () in
+ let int63_ty = locate_int63 () in
+ let ty_name = ty in
+ let ty, via =
+ match via with None -> ty, via | Some (ty', a) -> ty', Some (ty, a) in
+ let tyc, params = locate_global_inductive (via = None) ty in
+ let to_ty = Smartlocate.global_with_alias f in
+ let of_ty = Smartlocate.global_with_alias g in
+ let cty = mkRefC ty in
+ let app x y = mkAppC (x,[y]) in
+ let arrow x y =
+ mkProdC ([CAst.make Anonymous],Default Glob_term.Explicit, x, y)
+ in
+ let opt r = app (mkRefC (q_option ())) r in
+ (* Check the type of f *)
+ let to_kind =
+ match num_ty with
+ | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma f (arrow cint cty) -> Int int_ty, Direct
+ | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma f (arrow cint (opt cty)) -> Int int_ty, Option
+ | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma f (arrow cuint cty) -> UInt int_ty, Direct
+ | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma f (arrow cuint (opt cty)) -> UInt int_ty, Option
+ | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma f (arrow cnum cty) -> Number num_ty, Direct
+ | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma f (arrow cnum (opt cty)) -> Number num_ty, Option
+ | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma f (arrow cint cty) -> DecimalInt int_ty, Direct
+ | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma f (arrow cint (opt cty)) -> DecimalInt int_ty, Option
+ | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma f (arrow cuint cty) -> DecimalUInt int_ty, Direct
+ | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma f (arrow cuint (opt cty)) -> DecimalUInt int_ty, Option
+ | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma f (arrow cdec cty) -> Decimal num_ty, Direct
+ | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma f (arrow cdec (opt cty)) -> Decimal num_ty, Option
+ | _ ->
+ match z_pos_ty with
+ | Some (z_pos_ty, cZ) when has_type env sigma f (arrow cZ cty) -> Z z_pos_ty, Direct
+ | Some (z_pos_ty, cZ) when has_type env sigma f (arrow cZ (opt cty)) -> Z z_pos_ty, Option
+ | _ ->
+ match int63_ty with
+ | Some cint63 when has_type env sigma f (arrow cint63 cty) -> Int63, Direct
+ | Some cint63 when has_type env sigma f (arrow cint63 (opt cty)) -> Int63, Option
+ | _ -> type_error_to f ty
+ in
+ (* Check the type of g *)
+ let of_kind =
+ match num_ty with
+ | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma g (arrow cty cint) -> Int int_ty, Direct
+ | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma g (arrow cty (opt cint)) -> Int int_ty, Option
+ | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma g (arrow cty cuint) -> UInt int_ty, Direct
+ | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma g (arrow cty (opt cuint)) -> UInt int_ty, Option
+ | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma g (arrow cty cnum) -> Number num_ty, Direct
+ | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma g (arrow cty (opt cnum)) -> Number num_ty, Option
+ | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma g (arrow cty cint) -> DecimalInt int_ty, Direct
+ | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma g (arrow cty (opt cint)) -> DecimalInt int_ty, Option
+ | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma g (arrow cty cuint) -> DecimalUInt int_ty, Direct
+ | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma g (arrow cty (opt cuint)) -> DecimalUInt int_ty, Option
+ | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma g (arrow cty cdec) -> Decimal num_ty, Direct
+ | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma g (arrow cty (opt cdec)) -> Decimal num_ty, Option
+ | _ ->
+ match z_pos_ty with
+ | Some (z_pos_ty, cZ) when has_type env sigma g (arrow cty cZ) -> Z z_pos_ty, Direct
+ | Some (z_pos_ty, cZ) when has_type env sigma g (arrow cty (opt cZ)) -> Z z_pos_ty, Option
+ | _ ->
+ match int63_ty with
+ | Some cint63 when has_type env sigma g (arrow cty cint63) -> Int63, Direct
+ | Some cint63 when has_type env sigma g (arrow cty (opt cint63)) -> Int63, Option
+ | _ -> type_error_of g ty
+ in
+ (match to_kind, of_kind with
+ | ((DecimalInt _ | DecimalUInt _ | Decimal _), _), _
+ | _, ((DecimalInt _ | DecimalUInt _ | Decimal _), _) ->
+ warn_deprecated_decimal ()
+ | _ -> ());
+ let to_post, pt_refs = match via with
+ | None -> elaborate_to_post_params env sigma tyc params
+ | Some (ty, l) -> elaborate_to_post_via env sigma ty tyc l in
+ let o = { to_kind; to_ty; to_post; of_kind; of_ty; ty_name;
+ warning = opts }
+ in
+ (match opts, to_kind with
+ | Abstract _, (_, Option) -> warn_abstract_large_num_no_op o.to_ty
+ | _ -> ());
+ let i =
+ { pt_local = local;
+ pt_scope = scope;
+ pt_interp_info = NumberNotation o;
+ pt_required = Nametab.path_of_global (GlobRef.IndRef tyc),[];
+ pt_refs;
+ pt_in_match = true }
+ in
+ enable_prim_token_interpretation i
diff --git a/plugins/syntax/number.mli b/plugins/syntax/number.mli
new file mode 100644
index 0000000000..d7d28b29ed
--- /dev/null
+++ b/plugins/syntax/number.mli
@@ -0,0 +1,31 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+open Libnames
+open Vernacexpr
+open Notation
+
+(** * Number notation *)
+
+type number_string_via = qualid * (bool * qualid * qualid) list
+type number_option =
+ | After of numnot_option
+ | Via of number_string_via
+
+val vernac_number_notation : locality_flag ->
+ qualid ->
+ qualid -> qualid ->
+ number_option list ->
+ Notation_term.scope_name -> unit
+
+(** These are also used in string notations *)
+val locate_global_inductive : bool -> Libnames.qualid -> Names.inductive * Names.GlobRef.t option list
+val elaborate_to_post_params : Environ.env -> Evd.evar_map -> Names.inductive -> Names.GlobRef.t option list -> (Names.GlobRef.t * Names.GlobRef.t * Notation.to_post_arg list) list array * Names.GlobRef.t list
+val elaborate_to_post_via : Environ.env -> Evd.evar_map -> Libnames.qualid -> Names.inductive -> (bool * Libnames.qualid * Libnames.qualid) list -> (Names.GlobRef.t * Names.GlobRef.t * Notation.to_post_arg list) list array * Names.GlobRef.t list
diff --git a/plugins/syntax/number_string_notation_plugin.mlpack b/plugins/syntax/number_string_notation_plugin.mlpack
new file mode 100644
index 0000000000..74c32d3a53
--- /dev/null
+++ b/plugins/syntax/number_string_notation_plugin.mlpack
@@ -0,0 +1,3 @@
+Number
+String_notation
+G_number_string
diff --git a/plugins/syntax/numeral.ml b/plugins/syntax/numeral.ml
deleted file mode 100644
index 2db76719b8..0000000000
--- a/plugins/syntax/numeral.ml
+++ /dev/null
@@ -1,217 +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) *)
-(************************************************************************)
-
-open Pp
-open Util
-open Names
-open Libnames
-open Constrexpr
-open Constrexpr_ops
-open Notation
-
-(** * Numeral notation *)
-
-let warn_abstract_large_num_no_op =
- CWarnings.create ~name:"abstract-large-number-no-op" ~category:"numbers"
- (fun f ->
- strbrk "The 'abstract after' directive has no effect when " ++
- strbrk "the parsing function (" ++
- Nametab.pr_global_env (Termops.vars_of_env (Global.env ())) f ++ strbrk ") targets an " ++
- strbrk "option type.")
-
-let get_constructors ind =
- let mib,oib = Global.lookup_inductive ind in
- let mc = oib.Declarations.mind_consnames in
- Array.to_list
- (Array.mapi (fun j c -> GlobRef.ConstructRef (ind, j + 1)) mc)
-
-let qualid_of_ref n =
- n |> Coqlib.lib_ref |> Nametab.shortest_qualid_of_global Id.Set.empty
-
-let q_option () = qualid_of_ref "core.option.type"
-
-let unsafe_locate_ind q =
- match Nametab.locate q with
- | GlobRef.IndRef i -> i
- | _ -> raise Not_found
-
-let locate_z () =
- let zn = "num.Z.type" in
- let pn = "num.pos.type" in
- if Coqlib.has_ref zn && Coqlib.has_ref pn
- then
- let q_z = qualid_of_ref zn in
- let q_pos = qualid_of_ref pn in
- Some ({
- z_ty = unsafe_locate_ind q_z;
- pos_ty = unsafe_locate_ind q_pos;
- }, mkRefC q_z)
- else None
-
-let locate_numeral () =
- let dint = "num.int.type" in
- let duint = "num.uint.type" in
- let dec = "num.decimal.type" in
- let hint = "num.hexadecimal_int.type" in
- let huint = "num.hexadecimal_uint.type" in
- let hex = "num.hexadecimal.type" in
- let int = "num.num_int.type" in
- let uint = "num.num_uint.type" in
- let num = "num.numeral.type" in
- if Coqlib.has_ref dint && Coqlib.has_ref duint && Coqlib.has_ref dec
- && Coqlib.has_ref hint && Coqlib.has_ref huint && Coqlib.has_ref hex
- && Coqlib.has_ref int && Coqlib.has_ref uint && Coqlib.has_ref num
- then
- let q_dint = qualid_of_ref dint in
- let q_duint = qualid_of_ref duint in
- let q_dec = qualid_of_ref dec in
- let q_hint = qualid_of_ref hint in
- let q_huint = qualid_of_ref huint in
- let q_hex = qualid_of_ref hex in
- let q_int = qualid_of_ref int in
- let q_uint = qualid_of_ref uint in
- let q_num = qualid_of_ref num in
- let int_ty = {
- dec_int = unsafe_locate_ind q_dint;
- dec_uint = unsafe_locate_ind q_duint;
- hex_int = unsafe_locate_ind q_hint;
- hex_uint = unsafe_locate_ind q_huint;
- int = unsafe_locate_ind q_int;
- uint = unsafe_locate_ind q_uint;
- } in
- let num_ty = {
- int = int_ty;
- decimal = unsafe_locate_ind q_dec;
- hexadecimal = unsafe_locate_ind q_hex;
- numeral = unsafe_locate_ind q_num;
- } in
- Some (int_ty, mkRefC q_int, mkRefC q_uint, mkRefC q_dint, mkRefC q_duint,
- num_ty, mkRefC q_num, mkRefC q_dec)
- else None
-
-let locate_int63 () =
- let int63n = "num.int63.type" in
- if Coqlib.has_ref int63n
- then
- let q_int63 = qualid_of_ref int63n in
- Some (mkRefC q_int63)
- else None
-
-let has_type env sigma f ty =
- let c = mkCastC (mkRefC f, Glob_term.CastConv ty) in
- try let _ = Constrintern.interp_constr env sigma c in true
- with Pretype_errors.PretypeError _ -> false
-
-let type_error_to f ty =
- CErrors.user_err
- (pr_qualid f ++ str " should go from Numeral.int to " ++
- pr_qualid ty ++ str " or (option " ++ pr_qualid ty ++ str ")." ++
- fnl () ++ str "Instead of Numeral.int, the types Numeral.uint or Z or Int63.int or Numeral.numeral could be used (you may need to require BinNums or Numeral or Int63 first).")
-
-let type_error_of g ty =
- CErrors.user_err
- (pr_qualid g ++ str " should go from " ++ pr_qualid ty ++
- str " to Numeral.int or (option Numeral.int)." ++ fnl () ++
- str "Instead of Numeral.int, the types Numeral.uint or Z or Int63.int or Numeral.numeral could be used (you may need to require BinNums or Numeral or Int63 first).")
-
-let warn_deprecated_decimal =
- CWarnings.create ~name:"decimal-numeral-notation" ~category:"deprecated"
- (fun () ->
- strbrk "Deprecated Numeral Notation for Decimal.uint, \
- Decimal.int or Decimal.decimal. Use Numeral.uint, \
- Numeral.int or Numeral.numeral respectively.")
-
-let vernac_numeral_notation local ty f g scope opts =
- let env = Global.env () in
- let sigma = Evd.from_env env in
- let num_ty = locate_numeral () in
- let z_pos_ty = locate_z () in
- let int63_ty = locate_int63 () in
- let tyc = Smartlocate.global_inductive_with_alias ty in
- let to_ty = Smartlocate.global_with_alias f in
- let of_ty = Smartlocate.global_with_alias g in
- let cty = mkRefC ty in
- let app x y = mkAppC (x,[y]) in
- let arrow x y =
- mkProdC ([CAst.make Anonymous],Default Glob_term.Explicit, x, y)
- in
- let opt r = app (mkRefC (q_option ())) r in
- let constructors = get_constructors tyc in
- (* Check the type of f *)
- let to_kind =
- match num_ty with
- | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma f (arrow cint cty) -> Int int_ty, Direct
- | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma f (arrow cint (opt cty)) -> Int int_ty, Option
- | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma f (arrow cuint cty) -> UInt int_ty, Direct
- | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma f (arrow cuint (opt cty)) -> UInt int_ty, Option
- | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma f (arrow cnum cty) -> Numeral num_ty, Direct
- | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma f (arrow cnum (opt cty)) -> Numeral num_ty, Option
- | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma f (arrow cint cty) -> DecimalInt int_ty, Direct
- | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma f (arrow cint (opt cty)) -> DecimalInt int_ty, Option
- | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma f (arrow cuint cty) -> DecimalUInt int_ty, Direct
- | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma f (arrow cuint (opt cty)) -> DecimalUInt int_ty, Option
- | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma f (arrow cdec cty) -> Decimal num_ty, Direct
- | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma f (arrow cdec (opt cty)) -> Decimal num_ty, Option
- | _ ->
- match z_pos_ty with
- | Some (z_pos_ty, cZ) when has_type env sigma f (arrow cZ cty) -> Z z_pos_ty, Direct
- | Some (z_pos_ty, cZ) when has_type env sigma f (arrow cZ (opt cty)) -> Z z_pos_ty, Option
- | _ ->
- match int63_ty with
- | Some cint63 when has_type env sigma f (arrow cint63 cty) -> Int63, Direct
- | Some cint63 when has_type env sigma f (arrow cint63 (opt cty)) -> Int63, Option
- | _ -> type_error_to f ty
- in
- (* Check the type of g *)
- let of_kind =
- match num_ty with
- | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma g (arrow cty cint) -> Int int_ty, Direct
- | Some (int_ty, cint, _, _, _, _, _, _) when has_type env sigma g (arrow cty (opt cint)) -> Int int_ty, Option
- | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma g (arrow cty cuint) -> UInt int_ty, Direct
- | Some (int_ty, _, cuint, _, _, _, _, _) when has_type env sigma g (arrow cty (opt cuint)) -> UInt int_ty, Option
- | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma g (arrow cty cnum) -> Numeral num_ty, Direct
- | Some (_, _, _, _, _, num_ty, cnum, _) when has_type env sigma g (arrow cty (opt cnum)) -> Numeral num_ty, Option
- | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma g (arrow cty cint) -> DecimalInt int_ty, Direct
- | Some (int_ty, _, _, cint, _, _, _, _) when has_type env sigma g (arrow cty (opt cint)) -> DecimalInt int_ty, Option
- | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma g (arrow cty cuint) -> DecimalUInt int_ty, Direct
- | Some (int_ty, _, _, _, cuint, _, _, _) when has_type env sigma g (arrow cty (opt cuint)) -> DecimalUInt int_ty, Option
- | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma g (arrow cty cdec) -> Decimal num_ty, Direct
- | Some (_, _, _, _, _, num_ty, _, cdec) when has_type env sigma g (arrow cty (opt cdec)) -> Decimal num_ty, Option
- | _ ->
- match z_pos_ty with
- | Some (z_pos_ty, cZ) when has_type env sigma g (arrow cty cZ) -> Z z_pos_ty, Direct
- | Some (z_pos_ty, cZ) when has_type env sigma g (arrow cty (opt cZ)) -> Z z_pos_ty, Option
- | _ ->
- match int63_ty with
- | Some cint63 when has_type env sigma g (arrow cty cint63) -> Int63, Direct
- | Some cint63 when has_type env sigma g (arrow cty (opt cint63)) -> Int63, Option
- | _ -> type_error_of g ty
- in
- (match to_kind, of_kind with
- | ((DecimalInt _ | DecimalUInt _ | Decimal _), _), _
- | _, ((DecimalInt _ | DecimalUInt _ | Decimal _), _) ->
- warn_deprecated_decimal ()
- | _ -> ());
- let o = { to_kind; to_ty; of_kind; of_ty;
- ty_name = ty;
- warning = opts }
- in
- (match opts, to_kind with
- | Abstract _, (_, Option) -> warn_abstract_large_num_no_op o.to_ty
- | _ -> ());
- let i =
- { pt_local = local;
- pt_scope = scope;
- pt_interp_info = NumeralNotation o;
- pt_required = Nametab.path_of_global (GlobRef.IndRef tyc),[];
- pt_refs = constructors;
- pt_in_match = true }
- in
- enable_prim_token_interpretation i
diff --git a/plugins/syntax/numeral.mli b/plugins/syntax/numeral.mli
deleted file mode 100644
index 99252484b4..0000000000
--- a/plugins/syntax/numeral.mli
+++ /dev/null
@@ -1,19 +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) *)
-(************************************************************************)
-
-open Libnames
-open Vernacexpr
-open Notation
-
-(** * Numeral notation *)
-
-val vernac_numeral_notation : locality_flag ->
- qualid -> qualid -> qualid ->
- Notation_term.scope_name -> numnot_option -> unit
diff --git a/plugins/syntax/numeral_notation_plugin.mlpack b/plugins/syntax/numeral_notation_plugin.mlpack
deleted file mode 100644
index f4d9cae3ff..0000000000
--- a/plugins/syntax/numeral_notation_plugin.mlpack
+++ /dev/null
@@ -1,2 +0,0 @@
-Numeral
-G_numeral
diff --git a/plugins/syntax/r_syntax.ml b/plugins/syntax/r_syntax.ml
deleted file mode 100644
index d66b9537b4..0000000000
--- a/plugins/syntax/r_syntax.ml
+++ /dev/null
@@ -1,214 +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) *)
-(************************************************************************)
-
-open Util
-open Names
-open Glob_term
-
-(* Poor's man DECLARE PLUGIN *)
-let __coq_plugin_name = "r_syntax_plugin"
-let () = Mltop.add_known_module __coq_plugin_name
-
-exception Non_closed_number
-
-(**********************************************************************)
-(* Parsing positive via scopes *)
-(**********************************************************************)
-
-let binnums = ["Coq";"Numbers";"BinNums"]
-
-let make_dir l = DirPath.make (List.rev_map Id.of_string l)
-let make_path dir id = Libnames.make_path (make_dir dir) (Id.of_string id)
-
-let is_gr c gr = match DAst.get c with
-| GRef (r, _) -> GlobRef.equal r gr
-| _ -> false
-
-let positive_modpath = MPfile (make_dir binnums)
-
-let positive_kn = MutInd.make2 positive_modpath (Label.make "positive")
-let path_of_xI = ((positive_kn,0),1)
-let path_of_xO = ((positive_kn,0),2)
-let path_of_xH = ((positive_kn,0),3)
-let glob_xI = GlobRef.ConstructRef path_of_xI
-let glob_xO = GlobRef.ConstructRef path_of_xO
-let glob_xH = GlobRef.ConstructRef path_of_xH
-
-let pos_of_bignat ?loc x =
- let ref_xI = DAst.make @@ GRef (glob_xI, None) in
- let ref_xH = DAst.make @@ GRef (glob_xH, None) in
- let ref_xO = DAst.make @@ GRef (glob_xO, None) in
- let rec pos_of x =
- match Z.(div_rem x (of_int 2)) with
- | (q,rem) when rem = Z.zero -> DAst.make @@ GApp (ref_xO,[pos_of q])
- | (q,_) when not Z.(equal q zero) -> DAst.make @@ GApp (ref_xI,[pos_of q])
- | (q,_) -> ref_xH
- in
- pos_of x
-
-(**********************************************************************)
-(* Printing positive via scopes *)
-(**********************************************************************)
-
-let rec bignat_of_pos c = match DAst.get c with
- | GApp (r, [a]) when is_gr r glob_xO -> Z.mul Z.(of_int 2) (bignat_of_pos a)
- | GApp (r, [a]) when is_gr r glob_xI -> Z.add Z.one Z.(mul (of_int 2) (bignat_of_pos a))
- | GRef (a, _) when GlobRef.equal a glob_xH -> Z.one
- | _ -> raise Non_closed_number
-
-(**********************************************************************)
-(* Parsing Z via scopes *)
-(**********************************************************************)
-
-let z_kn = MutInd.make2 positive_modpath (Label.make "Z")
-let path_of_ZERO = ((z_kn,0),1)
-let path_of_POS = ((z_kn,0),2)
-let path_of_NEG = ((z_kn,0),3)
-let glob_ZERO = GlobRef.ConstructRef path_of_ZERO
-let glob_POS = GlobRef.ConstructRef path_of_POS
-let glob_NEG = GlobRef.ConstructRef path_of_NEG
-
-let z_of_int ?loc n =
- if not Z.(equal n zero) then
- let sgn, n =
- if Z.(leq zero n) then glob_POS, n else glob_NEG, Z.neg n in
- DAst.make @@ GApp(DAst.make @@ GRef (sgn,None), [pos_of_bignat ?loc n])
- else
- DAst.make @@ GRef (glob_ZERO, None)
-
-(**********************************************************************)
-(* Printing Z via scopes *)
-(**********************************************************************)
-
-let bigint_of_z c = match DAst.get c with
- | GApp (r,[a]) when is_gr r glob_POS -> bignat_of_pos a
- | GApp (r,[a]) when is_gr r glob_NEG -> Z.neg (bignat_of_pos a)
- | GRef (a, _) when GlobRef.equal a glob_ZERO -> Z.zero
- | _ -> raise Non_closed_number
-
-(**********************************************************************)
-(* Parsing R via scopes *)
-(**********************************************************************)
-
-let rdefinitions = ["Coq";"Reals";"Rdefinitions"]
-let r_modpath = MPfile (make_dir rdefinitions)
-let r_base_modpath = MPdot (r_modpath, Label.make "RbaseSymbolsImpl")
-let r_path = make_path ["Coq";"Reals";"Rdefinitions";"RbaseSymbolsImpl"] "R"
-
-let glob_IZR = GlobRef.ConstRef (Constant.make2 r_modpath @@ Label.make "IZR")
-let glob_Rmult = GlobRef.ConstRef (Constant.make2 r_base_modpath @@ Label.make "Rmult")
-let glob_Rdiv = GlobRef.ConstRef (Constant.make2 r_modpath @@ Label.make "Rdiv")
-
-let binintdef = ["Coq";"ZArith";"BinIntDef"]
-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 n =
- let n,e = NumTok.Signed.to_bigint_and_exponent n in
- let e,p = NumTok.(match e with EDec e -> e, 10 | EBin e -> e, 2) in
- let izr z =
- DAst.make @@ GApp (DAst.make @@ GRef(glob_IZR,None), [z]) in
- let rmult r r' =
- DAst.make @@ GApp (DAst.make @@ GRef(glob_Rmult,None), [r; r']) in
- let rdiv r r' =
- DAst.make @@ GApp (DAst.make @@ GRef(glob_Rdiv,None), [r; r']) in
- let pow p e =
- let p = z_of_int ?loc (Z.of_int p) in
- let e = pos_of_bignat e in
- DAst.make @@ GApp (DAst.make @@ GRef(glob_pow_pos,None), [p; e]) in
- let n =
- izr (z_of_int ?loc n) in
- if Int.equal (Z.sign e) 1 then rmult n (izr (pow p e))
- else if Int.equal (Z.sign e) (-1) then rdiv n (izr (pow p (Z.neg e)))
- else n (* e = 0 *)
-
-(**********************************************************************)
-(* Printing R via scopes *)
-(**********************************************************************)
-
-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 Int.equal (Z.sign e) 1 then
- true (* don't print 12 * 10^2 as 1200 to distinguish them *)
- else
- let i = Z.to_string i in
- let li = if i.[0] = '-' then String.length i - 1 else String.length i in
- let e = Z.neg e in
- let le = String.length (Z.to_string e) in
- Z.(lt (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 (NumTok.EDec e) in
- (* print 123 * 10^-2 as 1.23, precondition e < 0 *)
- let numTok_dot () =
- let s, i =
- if Z.sign i >= 0 then NumTok.SPlus, Z.to_string i
- else NumTok.SMinus, Z.(to_string (neg i)) in
- let ni = String.length i in
- let e = - (Z.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_int_frac_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
- NumTok.(Signed.of_bigint CDec 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])
- when is_gr i glob_IZR && is_gr i' glob_IZR ->
- begin match DAst.get r with
- | GApp (p, [t; e]) when is_gr p glob_pow_pos ->
- let t = bigint_of_z t in
- if not (Z.(equal t (of_int 10))) then
- raise Non_closed_number
- else
- let i = bigint_of_z l in
- let e = bignat_of_pos e in
- let e = if is_gr md glob_Rdiv then Z.neg e else e in
- numTok_of_int_exp i e
- | _ -> raise Non_closed_number
- end
- | _ -> raise Non_closed_number
- end
- | _ -> raise Non_closed_number
-
-let uninterp_r (AnyGlobConstr p) =
- try
- Some (rawnum_of_r p)
- with Non_closed_number ->
- None
-
-open Notation
-
-let at_declare_ml_module f x =
- Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
-
-let r_scope = "R_scope"
-
-let _ =
- register_rawnumeral_interpretation r_scope (r_of_rawnum,uninterp_r);
- at_declare_ml_module enable_prim_token_interpretation
- { pt_local = false;
- pt_scope = r_scope;
- pt_interp_info = Uid r_scope;
- pt_required = (r_path,["Coq";"Reals";"Rdefinitions"]);
- pt_refs = [glob_IZR; glob_Rmult; glob_Rdiv];
- pt_in_match = false }
diff --git a/plugins/syntax/r_syntax.mli b/plugins/syntax/r_syntax.mli
deleted file mode 100644
index b72d544151..0000000000
--- a/plugins/syntax/r_syntax.mli
+++ /dev/null
@@ -1,9 +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) *)
-(************************************************************************)
diff --git a/plugins/syntax/r_syntax_plugin.mlpack b/plugins/syntax/r_syntax_plugin.mlpack
deleted file mode 100644
index d4ee75ea48..0000000000
--- a/plugins/syntax/r_syntax_plugin.mlpack
+++ /dev/null
@@ -1 +0,0 @@
-R_syntax
diff --git a/plugins/syntax/string_notation.ml b/plugins/syntax/string_notation.ml
index e7ed0d8061..774d59dda3 100644
--- a/plugins/syntax/string_notation.ml
+++ b/plugins/syntax/string_notation.ml
@@ -9,21 +9,15 @@
(************************************************************************)
open Pp
-open Util
open Names
open Libnames
open Constrexpr
open Constrexpr_ops
open Notation
+open Number
(** * String notation *)
-let get_constructors ind =
- let mib,oib = Global.lookup_inductive ind in
- let mc = oib.Declarations.mind_consnames in
- Array.to_list
- (Array.mapi (fun j c -> GlobRef.ConstructRef (ind, j + 1)) mc)
-
let qualid_of_ref n =
n |> Coqlib.lib_ref |> Nametab.shortest_qualid_of_global Id.Set.empty
@@ -46,7 +40,7 @@ let type_error_of g ty =
(pr_qualid g ++ str " should go from " ++ pr_qualid ty ++
str " to Byte.byte or (option Byte.byte) or (list Byte.byte) or (option (list Byte.byte)).")
-let vernac_string_notation local ty f g scope =
+let vernac_string_notation local ty f g via scope =
let env = Global.env () in
let sigma = Evd.from_env env in
let app x y = mkAppC (x,[y]) in
@@ -56,14 +50,16 @@ let vernac_string_notation local ty f g scope =
let coption = cref (q_option ()) in
let opt r = app coption r in
let clist_byte = app clist cbyte in
- let tyc = Smartlocate.global_inductive_with_alias ty in
+ let ty_name = ty in
+ let ty, via =
+ match via with None -> ty, via | Some (ty', a) -> ty', Some (ty, a) in
+ let tyc, params = locate_global_inductive (via = None) ty in
let to_ty = Smartlocate.global_with_alias f in
let of_ty = Smartlocate.global_with_alias g in
let cty = cref ty in
let arrow x y =
mkProdC ([CAst.make Anonymous],Default Glob_term.Explicit, x, y)
in
- let constructors = get_constructors tyc in
(* Check the type of f *)
let to_kind =
if has_type env sigma f (arrow clist_byte cty) then ListByte, Direct
@@ -80,11 +76,10 @@ let vernac_string_notation local ty f g scope =
else if has_type env sigma g (arrow cty (opt cbyte)) then Byte, Option
else type_error_of g ty
in
- let o = { to_kind = to_kind;
- to_ty = to_ty;
- of_kind = of_kind;
- of_ty = of_ty;
- ty_name = ty;
+ let to_post, pt_refs = match via with
+ | None -> elaborate_to_post_params env sigma tyc params
+ | Some (ty, l) -> elaborate_to_post_via env sigma ty tyc l in
+ let o = { to_kind; to_ty; to_post; of_kind; of_ty; ty_name;
warning = () }
in
let i =
@@ -92,7 +87,7 @@ let vernac_string_notation local ty f g scope =
pt_scope = scope;
pt_interp_info = StringNotation o;
pt_required = Nametab.path_of_global (GlobRef.IndRef tyc),[];
- pt_refs = constructors;
+ pt_refs;
pt_in_match = true }
in
enable_prim_token_interpretation i
diff --git a/plugins/syntax/string_notation.mli b/plugins/syntax/string_notation.mli
index 0d99f98d26..f3c7c969c6 100644
--- a/plugins/syntax/string_notation.mli
+++ b/plugins/syntax/string_notation.mli
@@ -14,5 +14,7 @@ open Vernacexpr
(** * String notation *)
val vernac_string_notation : locality_flag ->
- qualid -> qualid -> qualid ->
+ qualid ->
+ qualid -> qualid ->
+ Number.number_string_via option ->
Notation_term.scope_name -> unit
diff --git a/plugins/syntax/string_notation_plugin.mlpack b/plugins/syntax/string_notation_plugin.mlpack
deleted file mode 100644
index 6aa081dab4..0000000000
--- a/plugins/syntax/string_notation_plugin.mlpack
+++ /dev/null
@@ -1,2 +0,0 @@
-String_notation
-G_string
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 4a29db0dcf..5de0745d17 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -298,7 +298,7 @@ let inductive_template env sigma tmloc ind =
let ty = EConstr.of_constr ty in
let ty' = substl subst ty in
let sigma, e =
- Evarutil.new_evar env ~src:(hole_source n) ~typeclass_candidate:false sigma ty'
+ Evarutil.new_evar env ~src:(hole_source n) sigma ty'
in
(sigma, e::subst,e::evarl,n+1)
| LocalDef (na,b,ty) ->
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml
index 4091e5329c..cbf539c1e9 100644
--- a/pretyping/evarconv.ml
+++ b/pretyping/evarconv.ml
@@ -567,8 +567,13 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) flags env evd pbty
let compare_heads evd =
match EConstr.kind evd term, EConstr.kind evd term' with
| Const (c, u), Const (c', u') when QConstant.equal env c c' ->
- let u = EInstance.kind evd u and u' = EInstance.kind evd u' in
- check_strict evd u u'
+ if Int.equal (Stack.args_size sk) 1 && Environ.is_array_type env c
+ then
+ let u = EInstance.kind evd u and u' = EInstance.kind evd u' in
+ compare_cumulative_instances evd [|Univ.Variance.Irrelevant|] u u'
+ else
+ let u = EInstance.kind evd u and u' = EInstance.kind evd u' in
+ check_strict evd u u'
| Const _, Const _ -> UnifFailure (evd, NotSameHead)
| Ind ((mi,i) as ind , u), Ind (ind', u') when Names.Ind.CanOrd.equal ind ind' ->
if EInstance.is_empty u && EInstance.is_empty u' then Success evd
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index bdf3495479..f42c754ef5 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -523,6 +523,7 @@ let rec cases_pattern_of_glob_constr env na c =
| Anonymous -> PatVar (Name id)
end
| GHole (_,_,_) -> PatVar na
+ | GRef (GlobRef.VarRef id,_) -> PatVar (Name id)
| GRef (GlobRef.ConstructRef cstr,_) -> PatCstr (cstr,[],na)
| GApp (c, l) ->
begin match DAst.get c with
diff --git a/pretyping/nativenorm.ml b/pretyping/nativenorm.ml
index 3f68e3c78f..d06d6e01d1 100644
--- a/pretyping/nativenorm.ml
+++ b/pretyping/nativenorm.ml
@@ -525,7 +525,7 @@ let native_norm env sigma c ty =
if print_timing then Feedback.msg_info (Pp.str time_info);
let profiler_pid = if profile then start_profiler () else None in
let t0 = Unix.gettimeofday () in
- Nativelib.call_linker ~fatal:true env ~prefix fn (Some upd);
+ Nativelib.call_linker ~fatal:true ~prefix fn (Some upd);
let t1 = Unix.gettimeofday () in
if profile then stop_profiler profiler_pid;
let time_info = Format.sprintf "native_compute: Evaluation done in %.5f" (t1 -. t0) in
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index 06f7d92e62..b70ff20e32 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -139,7 +139,7 @@ let interp_known_universe_level_name evd qid =
let qid = Nametab.locate_universe qid in
Univ.Level.make qid
-let interp_universe_level_name ~anon_rigidity evd qid =
+let interp_universe_level_name evd qid =
try evd, interp_known_universe_level_name evd qid
with Not_found ->
if Libnames.qualid_is_ident qid then (* Undeclared *)
@@ -162,21 +162,15 @@ let interp_universe_level_name ~anon_rigidity evd qid =
with UGraph.AlreadyDeclared -> evd
in evd, level
-let interp_universe_name ?loc evd l =
- (* [univ_flexible_alg] can produce algebraic universes in terms *)
- let anon_rigidity = univ_flexible in
- let evd', l = interp_universe_level_name ~anon_rigidity evd l in
- evd', l
-
-let interp_sort_name ?loc sigma = function
+let interp_sort_name sigma = function
| GSProp -> sigma, Univ.Level.sprop
| GProp -> sigma, Univ.Level.prop
| GSet -> sigma, Univ.Level.set
- | GType l -> interp_universe_name ?loc sigma l
+ | GType l -> interp_universe_level_name sigma l
let interp_sort_info ?loc evd l =
List.fold_left (fun (evd, u) (l,n) ->
- let evd', u' = interp_sort_name ?loc evd l in
+ let evd', u' = interp_sort_name evd l in
let u' = Univ.Universe.make u' in
let u' = match n with
| 0 -> u'
@@ -410,7 +404,7 @@ let interp_known_glob_level ?loc evd = function
let interp_glob_level ?loc evd : glob_level -> _ = function
| UAnonymous {rigid} -> new_univ_level_variable ?loc (if rigid then univ_rigid else univ_flexible) evd
- | UNamed s -> interp_sort_name ?loc evd s
+ | UNamed s -> interp_sort_name evd s
let interp_instance ?loc evd l =
let evd, l' =
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index 4d37c0ef60..982814fdfc 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -687,6 +687,17 @@ let eta_constructor_app env sigma f l1 term =
| _ -> assert false)
| _ -> assert false
+(* If the terms are irrelevant, check that they have the same type. *)
+let careful_infer_conv ~pb ~ts env sigma m n =
+ if Retyping.relevance_of_term env sigma m == Sorts.Irrelevant &&
+ Retyping.relevance_of_term env sigma n == Sorts.Irrelevant
+ then
+ let tm = Retyping.get_type_of env sigma m in
+ let tn = Retyping.get_type_of env sigma n in
+ Option.bind (infer_conv ~pb:CONV ~ts env sigma tm tn)
+ (fun sigma -> infer_conv ~pb ~ts env sigma m n)
+ else infer_conv ~pb ~ts env sigma m n
+
let rec unify_0_with_initial_metas (sigma,ms,es as subst : subst0) conv_at_top env cv_pb flags m n =
let rec unirec_rec (curenv,nb as curenvnb) pb opt ((sigma,metasubst,evarsubst) as substn : subst0) curm curn =
let cM = Evarutil.whd_head_evar sigma curm
@@ -1127,7 +1138,7 @@ let rec unify_0_with_initial_metas (sigma,ms,es as subst : subst0) conv_at_top e
None
else
let ans = match flags.modulo_conv_on_closed_terms with
- | Some convflags -> infer_conv ~pb:cv_pb ~ts:convflags env sigma m n
+ | Some convflags -> careful_infer_conv ~pb:cv_pb ~ts:convflags env sigma m n
| _ -> constr_cmp cv_pb env sigma flags m n in
match ans with
| Some sigma -> ans
diff --git a/printing/ppconstr.ml b/printing/ppconstr.ml
index 8da1d636f0..e312c68b7d 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 (NumTok.SPlus,_) -> lposint
- | Numeral (NumTok.SMinus,_) -> lnegint
+ | Number (NumTok.SPlus,_) -> lposint
+ | Number (NumTok.SMinus,_) -> lnegint
| String _ -> latom
let print_hunks n pr pr_patt pr_binders (terms, termlists, binders, binderlists) unps =
@@ -222,7 +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 n -> NumTok.Signed.print n
+ | Number n -> NumTok.Signed.print n
| String s -> qs s
let pr_evar pr id l =
@@ -681,13 +681,10 @@ let tag_var = tag Tag.variable
| CDelimiters (sc,a) ->
return (pr_delimiters sc (pr mt (LevelLe ldelim) a), ldelim)
| CArray(u, t,def,ty) ->
- let pp = ref (str " |"++ spc () ++ pr mt ltop def
- ++ pr_opt_type_spc (pr mt) ty ++ str " |]" ++ pr_universe_instance u) in
- for i = Array.length t - 1 downto 1 do
- pp := str ";" ++ pr mt ltop t.(i) ++ !pp
- done;
- pp := pr mt ltop t.(0) ++ !pp;
- hov 0 (str "[|" ++ !pp), 0
+ hov 0 (str "[| " ++ prvect_with_sep (fun () -> str "; ") (pr mt ltop) t ++
+ (if not (Array.is_empty t) then str " " else mt()) ++
+ str "|" ++ spc() ++ pr mt ltop def ++ pr_opt_type_spc (pr mt) ty ++
+ str " |]" ++ pr_universe_instance u), 0
in
let loc = constr_loc a in
pr_with_comments ?loc
diff --git a/printing/printer.ml b/printing/printer.ml
index be1cc0d64a..ea718526de 100644
--- a/printing/printer.ml
+++ b/printing/printer.ml
@@ -45,6 +45,8 @@ let should_gname =
~key:["Printing";"Goal";"Names"]
~value:false
+let print_goal_names = should_gname (* for export *)
+
(**********************************************************************)
(** Terms *)
diff --git a/printing/printer.mli b/printing/printer.mli
index a25cbebe91..ea388ae57e 100644
--- a/printing/printer.mli
+++ b/printing/printer.mli
@@ -264,3 +264,6 @@ val pr_goal_by_id : proof:Proof.t -> Id.t -> Pp.t
val pr_goal_emacs : proof:Proof.t option -> int -> int -> Pp.t
val pr_typing_flags : Declarations.typing_flags -> Pp.t
+
+(** Tells if flag "Printing Goal Names" is activated *)
+val print_goal_names : unit -> bool
diff --git a/stm/stm.ml b/stm/stm.ml
index 85f889c879..df7e35beb5 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -2275,8 +2275,9 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
), true, true
| `MaybeASync (start, nodes, name, delegate) -> (fun () ->
reach ~cache:true start;
- (* no sections *)
- if CList.is_empty (Environ.named_context (Global.env ()))
+ if CList.is_empty (Environ.named_context (Global.env ())) (* no sections *)
+ || PG_compat.get_pstate () |> (* #[using] attribute *)
+ Option.cata (fun x -> Option.has_some (Declare.Proof.get_used_variables x)) false
then Util.pi1 (aux (`ASync (start, nodes, name, delegate))) ()
else Util.pi1 (aux (`Sync (name, `NoPU_NoHint_NoES))) ()
), not redefine_qed, true
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index ed92a85a12..9e66e8668f 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -482,8 +482,7 @@ let make_resolve_hyp env sigma st only_classes pri decl =
let keep = not only_classes || is_class in
if keep then
let id = GlobRef.VarRef id in
- let name = PathHints [id] in
- (make_resolves env sigma pri ~name ~check:false (IsGlobRef id))
+ make_resolves env sigma pri id
else []
let make_hints g (modes,st) only_classes sign =
diff --git a/tactics/hints.ml b/tactics/hints.ml
index fe3efef7c5..68229dbe26 100644
--- a/tactics/hints.ml
+++ b/tactics/hints.ml
@@ -1347,6 +1347,10 @@ let add_hints ~locality dbnames h =
| HintsExternEntry (info, tacexp) ->
add_externs info tacexp ~local ~superglobal dbnames
+let hint_globref gr = IsGlobRef gr
+
+let hint_constr (c, diff) = IsConstr (c, diff)
+
let expand_constructor_hints env sigma lems =
List.map_append (fun (evd,lem) ->
match EConstr.kind sigma lem with
@@ -1365,8 +1369,9 @@ let constructor_hints env sigma eapply lems =
List.map_append (fun lem ->
make_resolves env sigma (eapply, true) empty_hint_info ~check:true lem) lems
-let make_resolves env sigma info ~check ?name hint =
- make_resolves env sigma (true, false) info ~check ?name hint
+let make_resolves env sigma info hint =
+ let name = PathHints [hint] in
+ make_resolves env sigma (true, false) info ~check:false ~name (IsGlobRef hint)
let make_local_hint_db env sigma ts eapply lems =
let map c = c env sigma in
diff --git a/tactics/hints.mli b/tactics/hints.mli
index dd22cff10b..3d4d9c7970 100644
--- a/tactics/hints.mli
+++ b/tactics/hints.mli
@@ -167,9 +167,7 @@ type hint_db = Hint_db.t
type hnf = bool
-type hint_term =
- | IsGlobRef of GlobRef.t
- | IsConstr of constr * Univ.ContextSet.t option [@ocaml.deprecated "Declare a hint constant instead"]
+type hint_term
type hints_entry =
| HintsResolveEntry of (hint_info * hnf * hints_path_atom * hint_term) list
@@ -199,8 +197,10 @@ val current_pure_db : unit -> hint_db list
val add_hints : locality:Goptions.option_locality -> hint_db_name list -> hints_entry -> unit
-val prepare_hint : bool (* Check no remaining evars *) ->
- env -> evar_map -> evar_map * constr -> (constr * Univ.ContextSet.t)
+val hint_globref : GlobRef.t -> hint_term
+
+val hint_constr : constr * Univ.ContextSet.t option -> hint_term
+[@ocaml.deprecated "Declare a hint constant instead"]
(** A constr which is Hint'ed will be:
- (1) used as an Exact, if it does not start with a product
@@ -210,8 +210,7 @@ val prepare_hint : bool (* Check no remaining evars *) ->
has missing arguments. *)
val make_resolves :
- env -> evar_map -> hint_info -> check:bool -> ?name:hints_path_atom ->
- hint_term -> hint_entry list
+ env -> evar_map -> hint_info -> GlobRef.t -> hint_entry list
(** [make_resolve_hyp hname htyp].
used to add an hypothesis to the local hint database;
diff --git a/tactics/ind_tables.ml b/tactics/ind_tables.ml
index 9164a4ff26..b16153a39e 100644
--- a/tactics/ind_tables.ml
+++ b/tactics/ind_tables.ml
@@ -100,9 +100,9 @@ let check_scheme kind ind = Option.has_some (lookup_scheme kind ind)
let define internal role id c poly univs =
let id = compute_name internal id in
- let ctx = UState.minimize univs in
- let c = UnivSubst.nf_evars_and_universes_opt_subst (fun _ -> None) (UState.subst ctx) c in
- let univs = UState.univ_entry ~poly ctx in
+ let uctx = UState.minimize univs in
+ let c = UnivSubst.nf_evars_and_universes_opt_subst (fun _ -> None) (UState.subst uctx) c in
+ let univs = UState.univ_entry ~poly uctx in
!declare_definition_scheme ~internal ~univs ~role ~name:id c
(* Assumes that dependencies are already defined *)
diff --git a/test-suite/Makefile b/test-suite/Makefile
index 6c373701cf..279f32c903 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -36,7 +36,8 @@ include ../Makefile.common
# Note that this will later need an eval in shell to interpret the quotes
ROOT='$(shell cd ..; pwd)'
-ifneq ($(wildcard ../_build),)
+ifneq ($(wildcard ../_build/default/config/Makefile),)
+include ../_build/default/config/Makefile
BIN:=$(ROOT)/_build/install/default/bin/
# COQLIB is an env variable so no quotes
COQLIB:=$(shell cd ..; pwd)/_build/install/default/lib/coq
diff --git a/test-suite/bugs/closed/bug_10972.v b/test-suite/bugs/closed/bug_10972.v
new file mode 100644
index 0000000000..945c23c9a4
--- /dev/null
+++ b/test-suite/bugs/closed/bug_10972.v
@@ -0,0 +1,9 @@
+(* Check rewrite_strat is compatible with Ltac *)
+Require Import Coq.Setoids.Setoid.
+Module foo.
+ Definition Foo := True.
+ Ltac foo := rewrite_strat eval cbv [Foo].
+End foo.
+Goal foo.Foo.
+ foo.foo.
+Abort.
diff --git a/test-suite/bugs/closed/bug_13078.v b/test-suite/bugs/closed/bug_13078.v
new file mode 100644
index 0000000000..ec04408fd1
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13078.v
@@ -0,0 +1,10 @@
+(* Check that rules with patterns are not registered for cases patterns *)
+Module PrintingTest.
+Declare Custom Entry test.
+Notation "& x" := (Some x) (in custom test at level 0, x pattern).
+Check fun x => match x with | None => None | Some tt => Some tt end.
+Notation "& x" := (Some x) (at level 0, x pattern).
+Check fun x => match x with | None => None | Some tt => Some tt end.
+End PrintingTest.
+
+Fail Notation "x &" := (Some x) (at level 0, x pattern).
diff --git a/test-suite/bugs/closed/bug_13131.v b/test-suite/bugs/closed/bug_13131.v
new file mode 100644
index 0000000000..b358ae3ecc
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13131.v
@@ -0,0 +1,6 @@
+Set Mangle Names.
+
+Class A := {}.
+
+Lemma foo `{A} : A.
+Proof. Fail exact H. assumption. Qed.
diff --git a/test-suite/bugs/closed/bug_13162.v b/test-suite/bugs/closed/bug_13162.v
new file mode 100644
index 0000000000..eacc8980a9
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13162.v
@@ -0,0 +1,7 @@
+
+Module Type T. End T.
+Module F (X:T). End F.
+Fail Import F.
+(* Error: Anomaly "Uncaught exception Not_found." *)
+
+Fail Import T.
diff --git a/test-suite/bugs/closed/bug_13178.v b/test-suite/bugs/closed/bug_13178.v
new file mode 100644
index 0000000000..d9c516c362
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13178.v
@@ -0,0 +1,3 @@
+Primitive array := #array_type.
+
+Check [| | 0 |].
diff --git a/test-suite/bugs/closed/bug_13216.v b/test-suite/bugs/closed/bug_13216.v
new file mode 100644
index 0000000000..54a28a9c53
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13216.v
@@ -0,0 +1,4 @@
+Class A.
+Declare Instance a:A.
+Inductive T `(A) := C.
+Definition f x := match x with C _ => 0 end.
diff --git a/test-suite/bugs/closed/bug_13276.v b/test-suite/bugs/closed/bug_13276.v
new file mode 100644
index 0000000000..15ac7e7b36
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13276.v
@@ -0,0 +1,9 @@
+From Coq Require Import Floats.
+Open Scope float_scope.
+
+Lemma foo :
+ let n := opp 0 in sub n 0 = n.
+Proof.
+cbv.
+apply eq_refl.
+Qed.
diff --git a/test-suite/bugs/closed/bug_13330.v b/test-suite/bugs/closed/bug_13330.v
new file mode 100644
index 0000000000..d13de2e58d
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13330.v
@@ -0,0 +1,17 @@
+Polymorphic Inductive path {A : Type} (x : A) : A -> Type :=
+ refl : path x x.
+
+Goal False.
+Proof.
+simple refine (let H : False := _ in _).
++ exact_no_check I.
++ assert (path true false -> path false true).
+ (** Create a dummy polymorphic side-effect *)
+ {
+ intro IHn.
+ rewrite IHn.
+ reflexivity.
+ }
+ exact H.
+Fail Qed.
+Abort.
diff --git a/test-suite/bugs/closed/bug_13348.v b/test-suite/bugs/closed/bug_13348.v
new file mode 100644
index 0000000000..d3d5d3e5b4
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13348.v
@@ -0,0 +1,10 @@
+Generalizable All Variables.
+
+Class Inhabited (A : Type) : Type := populate { inhabitant : A }.
+Arguments populate {_} _.
+
+Set Mangle Names.
+Axioms _0 _1 _2 : Prop.
+
+Instance impl_inhabited {A} {B} {_3:Inhabited B} : Inhabited (A -> B)
+ := populate (fun _ => inhabitant).
diff --git a/test-suite/bugs/closed/bug_13354.v b/test-suite/bugs/closed/bug_13354.v
new file mode 100644
index 0000000000..fbda10a9d2
--- /dev/null
+++ b/test-suite/bugs/closed/bug_13354.v
@@ -0,0 +1,10 @@
+
+Primitive array := #array_type.
+
+Definition testArray : array nat := [| 1; 2; 4 | 0 : nat |].
+
+Definition on_array {A:Type} (x:array A) : Prop := True.
+
+Check on_array testArray.
+
+Check @on_array nat testArray.
diff --git a/test-suite/bugs/opened/bug_3395.v b/test-suite/bugs/opened/bug_3395.v
deleted file mode 100644
index 70b3a48a06..0000000000
--- a/test-suite/bugs/opened/bug_3395.v
+++ /dev/null
@@ -1,232 +0,0 @@
-Require Import TestSuite.admit.
-(* File reduced by coq-bug-finder from originally 10918 lines, then 3649 lines to 3177 lines, then from 3189 lines to 3164 lines, then from 2653 lines to 2496 lines, 2653 lines, then from 1642 lines to 651 lines, then from 736 lines to 473 lines, then from 433 lines to 275 lines, then from 258 lines to 235 lines. *)
-Generalizable All Variables.
-Set Implicit Arguments.
-
-Arguments fst {_ _} _.
-Arguments snd {_ _} _.
-
-Axiom cheat : forall {T}, T.
-
-Reserved Notation "g 'o' f" (at level 40, left associativity).
-
-Inductive paths {A : Type} (a : A) : A -> Type := idpath : paths a a.
-Arguments idpath {A a} , [A] a.
-Notation "x = y" := (paths x y) : type_scope.
-
-Definition symmetry {A : Type} {x y : A} (p : x = y) : y = x
- := match p with idpath => idpath end.
-
-Delimit Scope morphism_scope with morphism.
-Delimit Scope category_scope with category.
-Delimit Scope object_scope with object.
-Record PreCategory (object : Type) :=
- Build_PreCategory' {
- object :> Type := object;
- morphism : object -> object -> Type;
- identity : forall x, morphism x x;
- compose : forall s d d',
- morphism d d'
- -> morphism s d
- -> morphism s d'
- where "f 'o' g" := (compose f g);
- associativity : forall x1 x2 x3 x4
- (m1 : morphism x1 x2)
- (m2 : morphism x2 x3)
- (m3 : morphism x3 x4),
- (m3 o m2) o m1 = m3 o (m2 o m1);
- associativity_sym : forall x1 x2 x3 x4
- (m1 : morphism x1 x2)
- (m2 : morphism x2 x3)
- (m3 : morphism x3 x4),
- m3 o (m2 o m1) = (m3 o m2) o m1;
- left_identity : forall a b (f : morphism a b), identity b o f = f;
- right_identity : forall a b (f : morphism a b), f o identity a = f;
- identity_identity : forall x, identity x o identity x = identity x
- }.
-Bind Scope category_scope with PreCategory.
-Arguments PreCategory {_}.
-Arguments identity {_} [!C%category] x%object : rename.
-
-Arguments compose {_} [!C%category s%object d%object d'%object] m1%morphism m2%morphism : rename.
-
-Infix "o" := compose : morphism_scope.
-
-Delimit Scope functor_scope with functor.
-Local Open Scope morphism_scope.
-Record Functor `(C : @PreCategory objC, D : @PreCategory objD) :=
- {
- object_of :> C -> D;
- morphism_of : forall s d, morphism C s d
- -> morphism D (object_of s) (object_of d);
- composition_of : forall s d d'
- (m1 : morphism C s d) (m2: morphism C d d'),
- morphism_of _ _ (m2 o m1)
- = (morphism_of _ _ m2) o (morphism_of _ _ m1);
- identity_of : forall x, morphism_of _ _ (identity x)
- = identity (object_of x)
- }.
-Bind Scope functor_scope with Functor.
-
-Arguments morphism_of {_} [C%category] {_} [D%category] F%functor [s%object d%object] m%morphism : rename, simpl nomatch.
-
-Notation "F '_1' m" := (morphism_of F m) (at level 10, no associativity) : morphism_scope.
-
-Class IsIsomorphism `{C : @PreCategory objC} {s d} (m : morphism C s d) :=
- {
- morphism_inverse : morphism C d s;
- left_inverse : morphism_inverse o m = identity _;
- right_inverse : m o morphism_inverse = identity _
- }.
-
-Definition opposite `(C : @PreCategory objC) : PreCategory
- := @Build_PreCategory'
- C
- (fun s d => morphism C d s)
- (identity (C := C))
- (fun _ _ _ m1 m2 => m2 o m1)
- (fun _ _ _ _ _ _ _ => @associativity_sym _ _ _ _ _ _ _ _ _)
- (fun _ _ _ _ _ _ _ => @associativity _ _ _ _ _ _ _ _ _)
- (fun _ _ => @right_identity _ _ _ _)
- (fun _ _ => @left_identity _ _ _ _)
- (@identity_identity _ C).
-
-Notation "C ^op" := (opposite C) (at level 3) : category_scope.
-
-Definition prod `(C : @PreCategory objC, D : @PreCategory objD) : @PreCategory (objC * objD).
- refine (@Build_PreCategory'
- (C * D)%type
- (fun s d => (morphism C (fst s) (fst d)
- * morphism D (snd s) (snd d))%type)
- (fun x => (identity (fst x), identity (snd x)))
- (fun s d d' m2 m1 => (fst m2 o fst m1, snd m2 o snd m1))
- _
- _
- _
- _
- _); admit.
-Defined.
-Infix "*" := prod : category_scope.
-
-Definition compose_functor `(C : @PreCategory objC, D : @PreCategory objD, E : @PreCategory objE) (G : Functor D E) (F : Functor C D) : Functor C E
- := Build_Functor
- C E
- (fun c => G (F c))
- (fun _ _ m => morphism_of G (morphism_of F m))
- cheat
- cheat.
-
-Infix "o" := compose_functor : functor_scope.
-
-Record NaturalTransformation `(C : @PreCategory objC, D : @PreCategory objD) (F G : Functor C D) :=
- Build_NaturalTransformation' {
- components_of :> forall c, morphism D (F c) (G c);
- commutes : forall s d (m : morphism C s d),
- components_of d o F _1 m = G _1 m o components_of s;
-
- commutes_sym : forall s d (m : C.(morphism) s d),
- G _1 m o components_of s = components_of d o F _1 m
- }.
-Definition functor_category `(C : @PreCategory objC, D : @PreCategory objD) : PreCategory
- := @Build_PreCategory' (Functor C D)
- (@NaturalTransformation _ C _ D)
- cheat
- cheat
- cheat
- cheat
- cheat
- cheat
- cheat.
-
-Definition opposite_functor `(F : @Functor objC C objD D) : Functor C^op D^op
- := Build_Functor (C^op) (D^op)
- (object_of F)
- (fun s d => morphism_of F (s := d) (d := s))
- (fun d' d s m1 m2 => composition_of F s d d' m2 m1)
- (identity_of F).
-
-Definition opposite_invL `(F : @Functor objC C^op objD D) : Functor C D^op
- := Build_Functor C (D^op)
- (object_of F)
- (fun s d => morphism_of F (s := d) (d := s))
- (fun d' d s m1 m2 => composition_of F s d d' m2 m1)
- (identity_of F).
-Notation "F ^op" := (opposite_functor F) : functor_scope.
-
-Notation "F ^op'L" := (opposite_invL F) (at level 3) : functor_scope.
-Definition fst `{C : @PreCategory objC, D : @PreCategory objD} : Functor (C * D) C
- := Build_Functor (C * D) C
- (@fst _ _)
- (fun _ _ => @fst _ _)
- (fun _ _ _ _ _ => idpath)
- (fun _ => idpath).
-
-Definition snd `{C : @PreCategory objC, D : @PreCategory objD} : Functor (C * D) D
- := Build_Functor (C * D) D
- (@snd _ _)
- (fun _ _ => @snd _ _)
- (fun _ _ _ _ _ => idpath)
- (fun _ => idpath).
-Definition prod_functor `(F : @Functor objC C objD D, F' : @Functor objC C objD' D')
-: Functor C (D * D')
- := Build_Functor
- C (D * D')
- (fun c => (F c, F' c))
- (fun s d m => (F _1 m, F' _1 m))%morphism
- cheat
- cheat.
-Definition pair `(F : @Functor objC C objD D, F' : @Functor objC' C' objD' D') : Functor (C * C') (D * D')
- := (prod_functor (F o fst) (F' o snd))%functor.
-Notation cat_of obj :=
- (@Build_PreCategory' obj
- (fun x y => forall _ : x, y)
- (fun _ x => x)
- (fun _ _ _ f g x => f (g x))%core
- (fun _ _ _ _ _ _ _ => idpath)
- (fun _ _ _ _ _ _ _ => idpath)
- (fun _ _ _ => idpath)
- (fun _ _ _ => idpath)
- (fun _ => idpath)).
-
-Definition hom_functor `(C : @PreCategory objC) : Functor (C^op * C) (cat_of Type)
- := Build_Functor _ _ cheat cheat cheat cheat.
-
-Definition induced_hom_natural_transformation `(F : @Functor objC C objD D)
-: NaturalTransformation (hom_functor C) (hom_functor D o pair F^op F)
- := Build_NaturalTransformation' _ _ cheat cheat cheat.
-
-Class IsFullyFaithful `(F : @Functor objC C objD D)
- := is_fully_faithful
- : forall x y : C,
- IsIsomorphism (induced_hom_natural_transformation F (x, y)).
-
-Definition coyoneda `(A : @PreCategory objA) : Functor A^op (@functor_category _ A _ (cat_of Type))
- := cheat.
-
-Definition yoneda `(A : @PreCategory objA) : Functor A (@functor_category _ A^op _ (cat_of Type))
- := (((coyoneda A^op)^op'L)^op'L)%functor.
-Definition coyoneda_embedding `(A : @PreCategory objA) : @IsFullyFaithful _ _ _ _ (@coyoneda _ A).
-Admitted.
-
-Definition yoneda_embedding_fast `(A : @PreCategory objA) : @IsFullyFaithful _ _ _ _ (@yoneda _ A).
-Proof.
- intros a b.
- pose proof (coyoneda_embedding A^op a b) as CYE.
- unfold yoneda.
- Time let t := (type of CYE) in
- let t' := (eval simpl in t) in pose proof ((fun (x : t) => (x : t')) CYE) as CYE'. (* Finished transaction in 0. secs (0.216013u,0.004s) *)
- Fail Timeout 1 let t := match goal with |- ?G => constr:(G) end in
- let t' := (eval simpl in t) in exact ((fun (x : t') => (x : t)) CYE').
- Time let t := match goal with |- ?G => constr:(G) end in
- let t' := (eval simpl in t) in exact ((fun (x : t') => (x : t)) CYE'). (* Finished transaction in 0. secs (0.248016u,0.s) *)
-Fail Timeout 2 Defined.
-Time Defined. (* Finished transaction in 1. secs (0.432027u,0.s) *)
-
-Definition yoneda_embedding `(A : @PreCategory objA) : @IsFullyFaithful _ _ _ _ (@yoneda _ A).
-Proof.
- intros a b.
- pose proof (coyoneda_embedding A^op a b) as CYE.
- unfold yoneda; simpl in *.
- Fail Timeout 1 exact CYE.
- Time exact CYE. (* Finished transaction in 0. secs (0.012001u,0.s) *)
-Abort.
diff --git a/test-suite/misc/13330.sh b/test-suite/misc/13330.sh
new file mode 100755
index 0000000000..7340559432
--- /dev/null
+++ b/test-suite/misc/13330.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+$coqc misc/13330/bug_13330.v
+R=$?
+
+if [ $R == 0 ]; then
+ exit 1
+else
+ exit 0
+fi
diff --git a/test-suite/misc/13330/bug_13330.v b/test-suite/misc/13330/bug_13330.v
new file mode 100644
index 0000000000..acf6e80c48
--- /dev/null
+++ b/test-suite/misc/13330/bug_13330.v
@@ -0,0 +1,16 @@
+Polymorphic Inductive path {A : Type} (x : A) : A -> Type :=
+ refl : path x x.
+
+Goal False.
+Proof.
+simple refine (let H : False := _ in _).
++ exact_no_check I.
++ assert (path true false -> path false true).
+ (** Create a dummy polymorphic side-effect *)
+ {
+ intro IHn.
+ rewrite IHn.
+ reflexivity.
+ }
+ exact H.
+Qed.
diff --git a/test-suite/output/ErrorLocation_13241_1.out b/test-suite/output/ErrorLocation_13241_1.out
new file mode 100644
index 0000000000..d899dd5d46
--- /dev/null
+++ b/test-suite/output/ErrorLocation_13241_1.out
@@ -0,0 +1,3 @@
+File "stdin", line 4, characters 0-1:
+Error: No product even after head-reduction.
+
diff --git a/test-suite/output/ErrorLocation_13241_1.v b/test-suite/output/ErrorLocation_13241_1.v
new file mode 100644
index 0000000000..3102b13fb8
--- /dev/null
+++ b/test-suite/output/ErrorLocation_13241_1.v
@@ -0,0 +1,5 @@
+Ltac a := intro.
+Ltac b := a.
+Goal True.
+b.
+Abort.
diff --git a/test-suite/output/ErrorLocation_13241_2.out b/test-suite/output/ErrorLocation_13241_2.out
new file mode 100644
index 0000000000..d899dd5d46
--- /dev/null
+++ b/test-suite/output/ErrorLocation_13241_2.out
@@ -0,0 +1,3 @@
+File "stdin", line 4, characters 0-1:
+Error: No product even after head-reduction.
+
diff --git a/test-suite/output/ErrorLocation_13241_2.v b/test-suite/output/ErrorLocation_13241_2.v
new file mode 100644
index 0000000000..b82f36ed6f
--- /dev/null
+++ b/test-suite/output/ErrorLocation_13241_2.v
@@ -0,0 +1,5 @@
+Ltac a _ := intro.
+Ltac b := a ().
+Goal True.
+b.
+Abort.
diff --git a/test-suite/output/Notations4.out b/test-suite/output/Notations4.out
index fa0c20bf73..a6fd39c29b 100644
--- a/test-suite/output/Notations4.out
+++ b/test-suite/output/Notations4.out
@@ -125,3 +125,57 @@ Warning: Notation "_ :=: _" was already used. [notation-overridden,parsing]
: Prop
fun x : nat => <{ x; (S x) }>
: nat -> nat
+exists p : nat, ▢_p (p >= 1)
+ : Prop
+▢_n (n >= 1)
+ : Prop
+The command has indeed failed with message:
+Found an inductive type while a variable name was expected.
+The command has indeed failed with message:
+Found a constructor while a variable name was expected.
+The command has indeed failed with message:
+Found a constant while a variable name was expected.
+exists x y : nat, ▢_(x, y) (x >= 1 /\ y >= 2)
+ : Prop
+▢_n (n >= 1)
+ : Prop
+The command has indeed failed with message:
+Found an inductive type while a pattern was expected.
+▢_tt (tt = tt)
+ : Prop
+The command has indeed failed with message:
+Found a constant while a pattern was expected.
+exists x y : nat, ▢_(x, y) (x >= 1 /\ y >= 2)
+ : Prop
+pseudo_force n (fun n : nat => n >= 1)
+ : Prop
+The command has indeed failed with message:
+Found an inductive type while a pattern was expected.
+▢_tt (tt = tt)
+ : Prop
+The command has indeed failed with message:
+Found a constant while a pattern was expected.
+exists x y : nat, myforce (x, y) (x >= 1 /\ y >= 2)
+ : Prop
+myforce n (n >= 1)
+ : Prop
+The command has indeed failed with message:
+Found an inductive type while a pattern was expected.
+myforce tt (tt = tt)
+ : Prop
+The command has indeed failed with message:
+Found a constant while a pattern was expected.
+id nat
+ : Set
+fun a : bool => id a
+ : bool -> bool
+fun nat : bool => id nat
+ : bool -> bool
+The command has indeed failed with message:
+Found an inductive type while a pattern was expected.
+!! nat, nat = true
+ : Prop
+!!! nat, nat = true
+ : Prop
+!!!! (nat, id), nat = true /\ id = false
+ : Prop
diff --git a/test-suite/output/Notations4.v b/test-suite/output/Notations4.v
index 6dadd8c7fe..0731819bba 100644
--- a/test-suite/output/Notations4.v
+++ b/test-suite/output/Notations4.v
@@ -124,7 +124,7 @@ Check r 2 3.
End I.
Require Import Coq.Numbers.Cyclic.Int63.Int63.
-Module NumeralNotations.
+Module NumberNotations.
Module Test17.
(** Test int63 *)
Declare Scope test17_scope.
@@ -134,7 +134,7 @@ Module NumeralNotations.
Number Notation myint63 of_int to_int : test17_scope.
Check let v := 0%test17 in v : myint63.
End Test17.
-End NumeralNotations.
+End NumberNotations.
Module K.
@@ -313,3 +313,104 @@ Notation "x" := x (in custom com_top at level 90, x custom com at level 90).
Check fun x => <{ x ; (S x) }>.
End CoercionEntryTransitivity.
+
+(* Some corner cases *)
+
+Module P.
+
+(* Basic rules:
+ - a section variable be used for itself and as a binding variable
+ - a global name cannot be used for itself and as a binding variable
+*)
+
+ Definition pseudo_force {A} (n:A) (P:A -> Prop) := forall n', n' = n -> P n'.
+
+ Module NotationMixedTermBinderAsIdent.
+
+ Notation "▢_ n P" := (pseudo_force n (fun n => P))
+ (at level 0, n ident, P at level 9, format "▢_ n P").
+ Check exists p, ▢_p (p >= 1).
+ Section S.
+ Variable n:nat.
+ Check ▢_n (n >= 1).
+ End S.
+ Fail Check ▢_nat (nat = bool).
+ Fail Check ▢_O (O >= 1).
+ Axiom n:nat.
+ Fail Check ▢_n (n >= 1).
+
+ End NotationMixedTermBinderAsIdent.
+
+ Module NotationMixedTermBinderAsPattern.
+
+ Notation "▢_ n P" := (pseudo_force n (fun n => P))
+ (at level 0, n pattern, P at level 9, format "▢_ n P").
+ Check exists x y, ▢_(x,y) (x >= 1 /\ y >= 2).
+ Section S.
+ Variable n:nat.
+ Check ▢_n (n >= 1).
+ End S.
+ Fail Check ▢_nat (nat = bool).
+ Check ▢_tt (tt = tt).
+ Axiom n:nat.
+ Fail Check ▢_n (n >= 1).
+
+ End NotationMixedTermBinderAsPattern.
+
+ Module NotationMixedTermBinderAsStrictPattern.
+
+ Notation "▢_ n P" := (pseudo_force n (fun n => P))
+ (at level 0, n strict pattern, P at level 9, format "▢_ n P").
+ Check exists x y, ▢_(x,y) (x >= 1 /\ y >= 2).
+ Section S.
+ Variable n:nat.
+ Check ▢_n (n >= 1).
+ End S.
+ Fail Check ▢_nat (nat = bool).
+ Check ▢_tt (tt = tt).
+ Axiom n:nat.
+ Fail Check ▢_n (n >= 1).
+
+ End NotationMixedTermBinderAsStrictPattern.
+
+ Module AbbreviationMixedTermBinderAsStrictPattern.
+
+ Notation myforce n P := (pseudo_force n (fun n => P)).
+ Check exists x y, myforce (x,y) (x >= 1 /\ y >= 2).
+ Section S.
+ Variable n:nat.
+ Check myforce n (n >= 1). (* strict hence not used for printing *)
+ End S.
+ Fail Check myforce nat (nat = bool).
+ Check myforce tt (tt = tt).
+ Axiom n:nat.
+ Fail Check myforce n (n >= 1).
+
+ End AbbreviationMixedTermBinderAsStrictPattern.
+
+ Module Bug4765Part.
+
+ Notation id x := ((fun y => y) x).
+ Check id nat.
+
+ Notation id' x := ((fun x => x) x).
+ Check fun a : bool => id' a.
+ Check fun nat : bool => id' nat.
+ Fail Check id' nat.
+
+ End Bug4765Part.
+
+ Module NotationBinderNotMixedWithTerms.
+
+ Notation "!! x , P" := (forall x, P) (at level 200, x pattern).
+ Check !! nat, nat = true.
+
+ Notation "!!! x , P" := (forall x, P) (at level 200).
+ Check !!! nat, nat = true.
+
+ Notation "!!!! x , P" := (forall x, P) (at level 200, x strict pattern).
+ Check !!!! (nat,id), nat = true /\ id = false.
+
+ End NotationBinderNotMixedWithTerms.
+
+End P.
diff --git a/test-suite/output/NumberNotations.out b/test-suite/output/NumberNotations.out
index 8065c8d311..60682edec8 100644
--- a/test-suite/output/NumberNotations.out
+++ b/test-suite/output/NumberNotations.out
@@ -1,9 +1,9 @@
The command has indeed failed with message:
-Unexpected term (nat -> nat) while parsing a numeral notation.
+Unexpected term (nat -> nat) while parsing a number notation.
The command has indeed failed with message:
-Unexpected non-option term opaque4 while parsing a numeral notation.
+Unexpected non-option term opaque4 while parsing a number notation.
The command has indeed failed with message:
-Unexpected term (fun (A : Type) (x : A) => x) while parsing a numeral
+Unexpected term (fun (A : Type) (x : A) => x) while parsing a number
notation.
let v := 0%ppp in v : punit
: punit
@@ -32,7 +32,7 @@ Warning: To avoid stack overflow, large numbers in punit are interpreted as
applications of pto_punits. [abstract-large-number,numbers]
The command has indeed failed with message:
In environment
-v := pto_punits (Numeral.UIntDec (Decimal.D1 Decimal.Nil)) : punit
+v := pto_punits (Number.UIntDecimal (Decimal.D1 Decimal.Nil)) : punit
The term "v" has type "punit@{Set}" while it is expected to have type
"punit@{u}".
S
@@ -61,7 +61,7 @@ The command has indeed failed with message:
In environment
v := 0 : nat
The term "v" has type "nat" while it is expected to have type "wuint".
- = {| unwrap := Numeral.UIntDec (Decimal.D0 Decimal.Nil) |}
+ = {| unwrap := Number.UIntDecimal (Decimal.D0 Decimal.Nil) |}
: wuint
let v := 0%wuint8' in v : wuint
: wuint
@@ -82,7 +82,7 @@ function (of_uint) targets an option type.
The command has indeed failed with message:
The 'abstract after' directive has no effect when the parsing function
(of_uint) targets an option type. [abstract-large-number-no-op,numbers]
-let v := of_uint (Numeral.UIntDec (Decimal.D1 Decimal.Nil)) in v : unit
+let v := of_uint (Number.UIntDecimal (Decimal.D1 Decimal.Nil)) in v : unit
: unit
let v := 0%test13 in v : unit
: unit
@@ -234,3 +234,282 @@ let v : ty := Build_ty Type type in v : ty
: Prop
1_000
: list nat
+0
+ : Set
+1
+ : Set
+2
+ : Set
+3
+ : Set
+Empty_set
+ : Set
+unit
+ : Set
+sum unit unit
+ : Set
+sum unit (sum unit unit)
+ : Set
+The command has indeed failed with message:
+Missing mapping for constructor Isum.
+The command has indeed failed with message:
+Iunit was already mapped to unit and cannot be remapped to unit.
+The command has indeed failed with message:
+add is not an inductive type.
+The command has indeed failed with message:
+add is not a constructor of an inductive type.
+The command has indeed failed with message:
+Missing mapping for constructor Iempty.
+File "stdin", line 574, characters 56-61:
+Warning: Type of I'sum seems incompatible with the type of sum.
+Expected type is: (I' -> I' -> I') instead of (I -> I' -> I').
+This might yield ill typed terms when using the notation.
+[via-type-mismatch,numbers]
+File "stdin", line 579, characters 32-33:
+Warning: I was already mapped to Set, mapping it also to
+nat might yield ill typed terms when using the notation.
+[via-type-remapping,numbers]
+File "stdin", line 579, characters 37-42:
+Warning: Type of Iunit seems incompatible with the type of O.
+Expected type is: I instead of I.
+This might yield ill typed terms when using the notation.
+[via-type-mismatch,numbers]
+The command has indeed failed with message:
+'via' and 'abstract' cannot be used together.
+File "stdin", line 659, characters 21-23:
+Warning: Type of I1 seems incompatible with the type of Fin.F1.
+Expected type is: (nat -> I) instead of I.
+This might yield ill typed terms when using the notation.
+[via-type-mismatch,numbers]
+File "stdin", line 659, characters 35-37:
+Warning: Type of IS seems incompatible with the type of Fin.FS.
+Expected type is: (nat -> I -> I) instead of (I -> I).
+This might yield ill typed terms when using the notation.
+[via-type-mismatch,numbers]
+The command has indeed failed with message:
+The term "0" has type "forall n : nat, Fin.t (S n)"
+while it is expected to have type "nat".
+0
+ : Fin.t (S ?n)
+where
+?n : [ |- nat]
+1
+ : Fin.t (S (S ?n))
+where
+?n : [ |- nat]
+2
+ : Fin.t (S (S (S ?n)))
+where
+?n : [ |- nat]
+3
+ : Fin.t (S (S (S (S ?n))))
+where
+?n : [ |- nat]
+0 : Fin.t 3
+ : Fin.t 3
+1 : Fin.t 3
+ : Fin.t 3
+2 : Fin.t 3
+ : Fin.t 3
+The command has indeed failed with message:
+The term "3" has type "Fin.t (S (S (S (S ?n))))"
+while it is expected to have type "Fin.t 3".
+@Fin.F1 ?n
+ : Fin.t (S ?n)
+where
+?n : [ |- nat]
+@Fin.FS (S ?n) (@Fin.F1 ?n)
+ : Fin.t (S (S ?n))
+where
+?n : [ |- nat]
+@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n))
+ : Fin.t (S (S (S ?n)))
+where
+?n : [ |- nat]
+@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))
+ : Fin.t (S (S (S (S ?n))))
+where
+?n : [ |- nat]
+@Fin.F1 (S (S O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+@Fin.FS (S (S O)) (@Fin.F1 (S O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+@Fin.FS (S (S O)) (@Fin.FS (S O) (@Fin.F1 O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+The command has indeed failed with message:
+The term
+ "@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))"
+has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type
+ "Fin.t (S (S (S O)))".
+0
+ : list unit
+1
+ : list unit
+2
+ : list unit
+2
+ : list unit
+0 :: 0 :: nil
+ : list nat
+0
+ : Ip nat bool
+1
+ : Ip nat bool
+2
+ : Ip nat bool
+3
+ : Ip nat bool
+1
+ : Ip nat bool
+1
+ : Ip nat bool
+1
+ : Ip nat bool
+1
+ : Ip nat bool
+Ip0 nat nat 1
+ : Ip nat nat
+Ip0 bool bool 1
+ : Ip bool bool
+Ip1 nat nat 1
+ : Ip nat nat
+Ip3 1 nat nat
+ : Ip nat nat
+Ip0 nat bool O
+ : Ip nat bool
+Ip1 bool nat (S O)
+ : Ip nat bool
+Ip2 nat (S (S O)) bool
+ : Ip nat bool
+Ip3 (S (S (S O))) nat bool
+ : Ip nat bool
+0
+ : 0 = 0
+eq_refl
+ : 1 = 1
+0
+ : 1 = 1
+2
+ : extra_list_unit
+cons O unit tt (cons O unit tt (nil O unit))
+ : extra_list unit
+0
+ : Set
+1
+ : Set
+2
+ : Set
+3
+ : Set
+Empty_set
+ : Set
+unit
+ : Set
+sum unit unit
+ : Set
+sum unit (sum unit unit)
+ : Set
+0
+ : Fin.t (S ?n)
+where
+?n : [ |- nat]
+1
+ : Fin.t (S (S ?n))
+where
+?n : [ |- nat]
+2
+ : Fin.t (S (S (S ?n)))
+where
+?n : [ |- nat]
+3
+ : Fin.t (S (S (S (S ?n))))
+where
+?n : [ |- nat]
+0 : Fin.t 3
+ : Fin.t 3
+1 : Fin.t 3
+ : Fin.t 3
+2 : Fin.t 3
+ : Fin.t 3
+The command has indeed failed with message:
+The term "3" has type "Fin.t (S (S (S (S ?n))))"
+while it is expected to have type "Fin.t 3".
+@Fin.F1 ?n
+ : Fin.t (S ?n)
+where
+?n : [ |- nat]
+@Fin.FS (S ?n) (@Fin.F1 ?n)
+ : Fin.t (S (S ?n))
+where
+?n : [ |- nat]
+@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n))
+ : Fin.t (S (S (S ?n)))
+where
+?n : [ |- nat]
+@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))
+ : Fin.t (S (S (S (S ?n))))
+where
+?n : [ |- nat]
+@Fin.F1 (S (S O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+@Fin.FS (S (S O)) (@Fin.F1 (S O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+@Fin.FS (S (S O)) (@Fin.FS (S O) (@Fin.F1 O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+The command has indeed failed with message:
+The term
+ "@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))"
+has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type
+ "Fin.t (S (S (S O)))".
+0
+ : Fin.t (S ?n)
+where
+?n : [ |- nat : Set]
+1
+ : Fin.t (S (S ?n))
+where
+?n : [ |- nat : Set]
+2
+ : Fin.t (S (S (S ?n)))
+where
+?n : [ |- nat : Set]
+3
+ : Fin.t (S (S (S (S ?n))))
+where
+?n : [ |- nat : Set]
+0 : Fin.t 3
+ : Fin.t 3
+1 : Fin.t 3
+ : Fin.t 3
+2 : Fin.t 3
+ : Fin.t 3
+The command has indeed failed with message:
+The term "3" has type "Fin.t (S (S (S (S ?n))))"
+while it is expected to have type "Fin.t 3".
+@Fin.F1 ?n
+ : Fin.t (S ?n)
+where
+?n : [ |- nat : Set]
+@Fin.FS (S ?n) (@Fin.F1 ?n)
+ : Fin.t (S (S ?n))
+where
+?n : [ |- nat : Set]
+@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n))
+ : Fin.t (S (S (S ?n)))
+where
+?n : [ |- nat : Set]
+@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))
+ : Fin.t (S (S (S (S ?n))))
+where
+?n : [ |- nat : Set]
+@Fin.F1 (S (S O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+@Fin.FS (S (S O)) (@Fin.F1 (S O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+@Fin.FS (S (S O)) (@Fin.FS (S O) (@Fin.F1 O)) : Fin.t (S (S (S O)))
+ : Fin.t (S (S (S O)))
+The command has indeed failed with message:
+The term
+ "@Fin.FS (S (S (S ?n))) (@Fin.FS (S (S ?n)) (@Fin.FS (S ?n) (@Fin.F1 ?n)))"
+has type "Fin.t (S (S (S (S ?n))))" while it is expected to have type
+ "Fin.t (S (S (S O)))".
diff --git a/test-suite/output/NumberNotations.v b/test-suite/output/NumberNotations.v
index e411005da3..718da13500 100644
--- a/test-suite/output/NumberNotations.v
+++ b/test-suite/output/NumberNotations.v
@@ -5,17 +5,17 @@ Declare Scope opaque_scope.
(* https://github.com/coq/coq/pull/8064#discussion_r202497516 *)
Module Test1.
Axiom hold : forall {A B C}, A -> B -> C.
- Definition opaque3 (x : Numeral.int) : Numeral.int := hold x (fix f (x : nat) : nat := match x with O => O | S n => S (f n) end).
- Number Notation Numeral.int opaque3 opaque3 : opaque_scope.
+ Definition opaque3 (x : Number.int) : Number.int := hold x (fix f (x : nat) : nat := match x with O => O | S n => S (f n) end).
+ Number Notation Number.int opaque3 opaque3 : opaque_scope.
Delimit Scope opaque_scope with opaque.
Fail Check 1%opaque.
End Test1.
(* https://github.com/coq/coq/pull/8064#discussion_r202497990 *)
Module Test2.
- Axiom opaque4 : option Numeral.int.
- Definition opaque6 (x : Numeral.int) : option Numeral.int := opaque4.
- Number Notation Numeral.int opaque6 opaque6 : opaque_scope.
+ Axiom opaque4 : option Number.int.
+ Definition opaque6 (x : Number.int) : option Number.int := opaque4.
+ Number Notation Number.int opaque6 opaque6 : opaque_scope.
Delimit Scope opaque_scope with opaque.
Open Scope opaque_scope.
Fail Check 1%opaque.
@@ -24,8 +24,8 @@ End Test2.
Declare Scope silly_scope.
Module Test3.
- Inductive silly := SILLY (v : Numeral.uint) (f : forall A, A -> A).
- Definition to_silly (v : Numeral.uint) := SILLY v (fun _ x => x).
+ Inductive silly := SILLY (v : Number.uint) (f : forall A, A -> A).
+ Definition to_silly (v : Number.uint) := SILLY v (fun _ x => x).
Definition of_silly (v : silly) := match v with SILLY v _ => v end.
Number Notation silly to_silly of_silly : silly_scope.
Delimit Scope silly_scope with silly.
@@ -45,15 +45,15 @@ Module Test4.
Declare Scope upp.
Declare Scope ppps.
Polymorphic NonCumulative Inductive punit := ptt.
- Polymorphic Definition pto_punit (v : Numeral.uint) : option punit := match Nat.of_num_uint v with O => Some ptt | _ => None end.
- Polymorphic Definition pto_punit_all (v : Numeral.uint) : punit := ptt.
- Polymorphic Definition pof_punit (v : punit) : Numeral.uint := Nat.to_num_uint 0.
- Definition to_punit (v : Numeral.uint) : option punit := match Nat.of_num_uint v with O => Some ptt | _ => None end.
- Definition of_punit (v : punit) : Numeral.uint := Nat.to_num_uint 0.
- Polymorphic Definition pto_unit (v : Numeral.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end.
- Polymorphic Definition pof_unit (v : unit) : Numeral.uint := Nat.to_num_uint 0.
- Definition to_unit (v : Numeral.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end.
- Definition of_unit (v : unit) : Numeral.uint := Nat.to_num_uint 0.
+ Polymorphic Definition pto_punit (v : Number.uint) : option punit := match Nat.of_num_uint v with O => Some ptt | _ => None end.
+ Polymorphic Definition pto_punit_all (v : Number.uint) : punit := ptt.
+ Polymorphic Definition pof_punit (v : punit) : Number.uint := Nat.to_num_uint 0.
+ Definition to_punit (v : Number.uint) : option punit := match Nat.of_num_uint v with O => Some ptt | _ => None end.
+ Definition of_punit (v : punit) : Number.uint := Nat.to_num_uint 0.
+ Polymorphic Definition pto_unit (v : Number.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end.
+ Polymorphic Definition pof_unit (v : unit) : Number.uint := Nat.to_num_uint 0.
+ Definition to_unit (v : Number.uint) : option unit := match Nat.of_num_uint v with O => Some tt | _ => None end.
+ Definition of_unit (v : unit) : Number.uint := Nat.to_num_uint 0.
Number Notation punit to_punit of_punit : pto.
Number Notation punit pto_punit of_punit : ppo.
Number Notation punit to_punit pof_punit : ptp.
@@ -83,7 +83,7 @@ Module Test4.
Polymorphic Definition pto_punits := pto_punit_all@{Set}.
Polymorphic Definition pof_punits := pof_punit@{Set}.
- Number Notation punit pto_punits pof_punits : ppps (abstract after 1).
+ Number Notation punit pto_punits pof_punits (abstract after 1) : ppps.
Delimit Scope ppps with ppps.
Universe u.
Constraint Set < u.
@@ -96,7 +96,7 @@ Module Test5.
End Test5.
Module Test6.
- (* Check that numeral notations on enormous terms don't take forever to print/parse *)
+ (* Check that number notations on enormous terms don't take forever to print/parse *)
(* Ackerman definition from https://stackoverflow.com/a/10303475/377022 *)
Fixpoint ack (n m : nat) : nat :=
match n with
@@ -113,15 +113,15 @@ Module Test6.
Local Set Primitive Projections.
Record > wnat := wrap { unwrap :> nat }.
- Definition to_uint (x : wnat) : Numeral.uint := Nat.to_num_uint x.
- Definition of_uint (x : Numeral.uint) : wnat := Nat.of_num_uint x.
+ Definition to_uint (x : wnat) : Number.uint := Nat.to_num_uint x.
+ Definition of_uint (x : Number.uint) : wnat := Nat.of_num_uint x.
Module Export Scopes.
Declare Scope wnat_scope.
Delimit Scope wnat_scope with wnat.
End Scopes.
Module Export Notations.
Export Scopes.
- Number Notation wnat of_uint to_uint : wnat_scope (abstract after 5000).
+ Number Notation wnat of_uint to_uint (abstract after 5000) : wnat_scope.
End Notations.
Set Printing Coercions.
Check let v := 0%wnat in v : wnat.
@@ -138,7 +138,7 @@ End Test6_2.
Module Test7.
Local Set Primitive Projections.
- Record wuint := wrap { unwrap : Numeral.uint }.
+ Record wuint := wrap { unwrap : Number.uint }.
Declare Scope wuint_scope.
Delimit Scope wuint_scope with wuint.
Number Notation wuint wrap unwrap : wuint_scope.
@@ -148,7 +148,7 @@ End Test7.
Module Test8.
Local Set Primitive Projections.
- Record wuint := wrap { unwrap : Numeral.uint }.
+ Record wuint := wrap { unwrap : Number.uint }.
Declare Scope wuint8_scope.
Declare Scope wuint8'_scope.
Delimit Scope wuint8_scope with wuint8.
@@ -177,7 +177,7 @@ Module Test9.
Delimit Scope wuint9'_scope with wuint9'.
Section with_let.
Local Set Primitive Projections.
- Record wuint := wrap { unwrap : Numeral.uint }.
+ Record wuint := wrap { unwrap : Number.uint }.
Let wrap' := wrap.
Let unwrap' := unwrap.
Local Notation wrap'' := wrap.
@@ -194,26 +194,26 @@ End Test9.
Module Test10.
(* Test that it is only a warning to add abstract after to an optional parsing function *)
Definition to_uint (v : unit) := Nat.to_num_uint 0.
- Definition of_uint (v : Numeral.uint) := match Nat.of_num_uint v with O => Some tt | _ => None end.
- Definition of_any_uint (v : Numeral.uint) := tt.
+ Definition of_uint (v : Number.uint) := match Nat.of_num_uint v with O => Some tt | _ => None end.
+ Definition of_any_uint (v : Number.uint) := tt.
Declare Scope unit_scope.
Declare Scope unit2_scope.
Delimit Scope unit_scope with unit.
Delimit Scope unit2_scope with unit2.
- Number Notation unit of_uint to_uint : unit_scope (abstract after 1).
+ Number Notation unit of_uint to_uint (abstract after 1) : unit_scope.
Local Set Warnings Append "+abstract-large-number-no-op".
(* Check that there is actually a warning here *)
- Fail Number Notation unit of_uint to_uint : unit2_scope (abstract after 1).
+ Fail Number Notation unit of_uint to_uint (abstract after 1) : unit2_scope.
(* Check that there is no warning here *)
- Number Notation unit of_any_uint to_uint : unit2_scope (abstract after 1).
+ Number Notation unit of_any_uint to_uint (abstract after 1) : unit2_scope.
End Test10.
Module Test12.
- (* Test for numeral notations on context variables *)
+ (* Test for number notations on context variables *)
Declare Scope test12_scope.
Delimit Scope test12_scope with test12.
Section test12.
- Context (to_uint : unit -> Numeral.uint) (of_uint : Numeral.uint -> unit).
+ Context (to_uint : unit -> Number.uint) (of_uint : Number.uint -> unit).
Number Notation unit of_uint to_uint : test12_scope.
Check let v := 1%test12 in v : unit.
@@ -221,15 +221,15 @@ Module Test12.
End Test12.
Module Test13.
- (* Test for numeral notations on notations which do not denote references *)
+ (* Test for number notations on notations which do not denote references *)
Declare Scope test13_scope.
Declare Scope test13'_scope.
Declare Scope test13''_scope.
Delimit Scope test13_scope with test13.
Delimit Scope test13'_scope with test13'.
Delimit Scope test13''_scope with test13''.
- Definition to_uint (x y : unit) : Numeral.uint := Nat.to_num_uint O.
- Definition of_uint (x : Numeral.uint) : unit := tt.
+ Definition to_uint (x y : unit) : Number.uint := Nat.to_num_uint O.
+ Definition of_uint (x : Number.uint) : unit := tt.
Definition to_uint_good := to_uint tt.
Notation to_uint' := (to_uint tt).
Notation to_uint'' := (to_uint _).
@@ -242,7 +242,7 @@ Module Test13.
End Test13.
Module Test14.
- (* Test that numeral notations follow [Import], not [Require], and
+ (* Test that number notations follow [Import], not [Require], and
also test that [Local Number Notation]s do not escape modules
nor sections. *)
Declare Scope test14_scope.
@@ -254,8 +254,8 @@ Module Test14.
Delimit Scope test14''_scope with test14''.
Delimit Scope test14'''_scope with test14'''.
Module Inner.
- Definition to_uint (x : unit) : Numeral.uint := Nat.to_num_uint O.
- Definition of_uint (x : Numeral.uint) : unit := tt.
+ Definition to_uint (x : unit) : Number.uint := Nat.to_num_uint O.
+ Definition of_uint (x : Number.uint) : unit := tt.
Local Number Notation unit of_uint to_uint : test14_scope.
Global Number Notation unit of_uint to_uint : test14'_scope.
Check let v := 0%test14 in v : unit.
@@ -267,8 +267,8 @@ Module Test14.
Fail Check let v := 0%test14 in v : unit.
Check let v := 0%test14' in v : unit.
Section InnerSection.
- Definition to_uint (x : unit) : Numeral.uint := Nat.to_num_uint O.
- Definition of_uint (x : Numeral.uint) : unit := tt.
+ Definition to_uint (x : unit) : Number.uint := Nat.to_num_uint O.
+ Definition of_uint (x : Number.uint) : unit := tt.
Local Number Notation unit of_uint to_uint : test14''_scope.
Fail Global Number Notation unit of_uint to_uint : test14'''_scope.
Check let v := 0%test14'' in v : unit.
@@ -283,8 +283,8 @@ Module Test15.
Declare Scope test15_scope.
Delimit Scope test15_scope with test15.
Module Inner.
- Definition to_uint (x : unit) : Numeral.uint := Nat.to_num_uint O.
- Definition of_uint (x : Numeral.uint) : unit := tt.
+ Definition to_uint (x : unit) : Number.uint := Nat.to_num_uint O.
+ Definition of_uint (x : Number.uint) : unit := tt.
Number Notation unit of_uint to_uint : test15_scope.
Check let v := 0%test15 in v : unit.
End Inner.
@@ -306,8 +306,8 @@ Module Test16.
End A.
Module F (a : A).
Inductive Foo := foo (_ : a.T).
- Definition to_uint (x : Foo) : Numeral.uint := Nat.to_num_uint O.
- Definition of_uint (x : Numeral.uint) : Foo := foo a.t.
+ Definition to_uint (x : Foo) : Number.uint := Nat.to_num_uint O.
+ Definition of_uint (x : Number.uint) : Foo := foo a.t.
Global Number Notation Foo of_uint to_uint : test16_scope.
Check let v := 0%test16 in v : Foo.
End F.
@@ -352,8 +352,8 @@ Module Test18.
Definition Q_of_nat (x : nat) : Q := {| num := x ; den := 1 ; reduced := transparentify (nat_eq_dec _ _) (gcd_good _) |}.
Definition nat_of_Q (x : Q) : option nat
:= if Nat.eqb x.(den) 1 then Some (x.(num)) else None.
- Definition Q_of_uint (x : Numeral.uint) : Q := Q_of_nat (Nat.of_num_uint x).
- Definition uint_of_Q (x : Q) : option Numeral.uint
+ Definition Q_of_uint (x : Number.uint) : Q := Q_of_nat (Nat.of_num_uint x).
+ Definition uint_of_Q (x : Q) : option Number.uint
:= option_map Nat.to_num_uint (nat_of_Q x).
Number Notation Q Q_of_uint uint_of_Q : Q_scope.
@@ -411,7 +411,7 @@ Module Test20.
Record > ty := { t : Type ; kt : known_type t }.
- Definition ty_of_uint (x : Numeral.uint) : option ty
+ Definition ty_of_uint (x : Number.uint) : option ty
:= match Nat.of_num_uint x with
| 0 => @Some ty zero
| 1 => @Some ty one
@@ -421,7 +421,7 @@ Module Test20.
| 5 => @Some ty type
| _ => None
end.
- Definition uint_of_ty (x : ty) : Numeral.uint
+ Definition uint_of_ty (x : ty) : Number.uint
:= Nat.to_num_uint match kt x with
| prop => 3
| set => 4
@@ -487,3 +487,488 @@ Check (-0)%Z.
*)
End Test22.
+
+(* Test the via ... mapping ... option *)
+Module Test23.
+
+Inductive sum (A : Set) (B : Set) : Set := pair : A -> B -> sum A B.
+
+Inductive I :=
+| Iempty : I
+| Iunit : I
+| Isum : I -> I -> I.
+
+Definition of_uint (x : Number.uint) : I :=
+ let fix f n :=
+ match n with
+ | O => Iempty
+ | S O => Iunit
+ | S n => Isum Iunit (f n)
+ end in
+ f (Nat.of_num_uint x).
+
+Definition to_uint (x : I) : Number.uint :=
+ let fix f i :=
+ match i with
+ | Iempty => O
+ | Iunit => 1
+ | Isum i1 i2 => f i1 + f i2
+ end in
+ Nat.to_num_uint (f x).
+
+Notation nSet := (Set) (only parsing). (* needed as a reference is expected in Number Notation and Set is syntactically not a reference *)
+Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum])
+ : type_scope.
+
+Local Open Scope type_scope.
+
+Check Empty_set.
+Check unit.
+Check sum unit unit.
+Check sum unit (sum unit unit).
+Set Printing All.
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Unset Printing All.
+
+(* Test error messages *)
+
+(* missing constructor *)
+Fail Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit])
+ : type_scope.
+
+(* duplicate constructor *)
+Fail Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum, unit => Iunit])
+ : type_scope.
+
+(* not an inductive *)
+Fail Number Notation nSet of_uint to_uint (via add
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum])
+ : type_scope.
+
+(* not a constructor *)
+Fail Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => add, sum => Isum])
+ : type_scope.
+
+(* put constructors of the wrong inductive ~~> missing constructors *)
+Fail Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => O, unit => S])
+ : type_scope.
+
+(* Test warnings *)
+
+(* wrong type *)
+Inductive I' :=
+| I'empty : I'
+| I'unit : I'
+| I'sum : I -> I' -> I'.
+Definition of_uint' (x : Number.uint) : I' := I'empty.
+Definition to_uint' (x : I') : Number.uint := Number.UIntDecimal Decimal.Nil.
+Number Notation nSet of_uint' to_uint' (via I'
+ mapping [Empty_set => I'empty, unit => I'unit, sum => I'sum])
+ : type_scope.
+
+(* wrong type mapping *)
+Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, O => Iunit, sum => Isum])
+ : type_scope.
+
+(* incompatibility with abstract (but warning is fine) *)
+Fail Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum],
+ abstract after 12)
+ : type_scope.
+Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum],
+ warning after 12)
+ : type_scope.
+
+(* Test reduction of types when building the notation *)
+
+Inductive foo := bar : match (true <: bool) with true => nat -> foo | false => True end.
+
+Definition foo_of_uint (x : Number.uint) : foo := bar (Nat.of_num_uint x).
+Definition foo_to_uint (x : foo) : Number.uint :=
+ match x with
+ | bar x => Nat.to_num_uint x
+ end.
+
+Number Notation foo foo_of_uint foo_to_uint (via foo mapping [bar => bar])
+ : type_scope.
+
+Inductive foo' := bar' : let n := nat in n -> foo'.
+
+Definition foo'_of_uint (x : Number.uint) : foo' := bar' (Nat.of_num_uint x).
+Definition foo'_to_uint (x : foo') : Number.uint :=
+ match x with
+ | bar' x => Nat.to_num_uint x
+ end.
+
+Number Notation foo' foo'_of_uint foo'_to_uint (via foo' mapping [bar' => bar'])
+ : type_scope.
+
+Inductive foo'' := bar'' : (nat <: Type) -> (foo'' <: Type).
+
+Definition foo''_of_uint (x : Number.uint) : foo'' := bar'' (Nat.of_num_uint x).
+Definition foo''_to_uint (x : foo'') : Number.uint :=
+ match x with
+ | bar'' x => Nat.to_num_uint x
+ end.
+
+Number Notation foo'' foo''_of_uint foo''_to_uint (via foo'' mapping [bar'' => bar''])
+ : type_scope.
+
+End Test23.
+
+(* Test the via ... mapping ... option with implicit arguments *)
+Require Vector.
+Module Test24.
+
+Import Vector.
+
+Inductive I :=
+| I1 : I
+| IS : I -> I.
+
+Definition of_uint (x : Number.uint) : I :=
+ let fix f n :=
+ match n with
+ | O => I1
+ | S n => IS (f n)
+ end in
+ f (Nat.of_num_uint x).
+
+Definition to_uint (x : I) : Number.uint :=
+ let fix f i :=
+ match i with
+ | I1 => O
+ | IS n => S (f n)
+ end in
+ Nat.to_num_uint (f x).
+
+Local Open Scope type_scope.
+
+(* ignoring implicit arguments doesn't work *)
+Number Notation Fin.t of_uint to_uint (via I
+ mapping [Fin.F1 => I1, Fin.FS => IS])
+ : type_scope.
+
+Fail Check 1.
+
+Number Notation Fin.t of_uint to_uint (via I
+ mapping [[Fin.F1] => I1, [Fin.FS] => IS])
+ : type_scope.
+
+Check Fin.F1.
+Check Fin.FS Fin.F1.
+Check Fin.FS (Fin.FS Fin.F1).
+Check Fin.FS (Fin.FS (Fin.FS Fin.F1)).
+Check Fin.F1 : Fin.t 3.
+Check Fin.FS Fin.F1 : Fin.t 3.
+Check Fin.FS (Fin.FS Fin.F1) : Fin.t 3.
+Fail Check Fin.FS (Fin.FS (Fin.FS Fin.F1)) : Fin.t 3.
+Set Printing All.
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Check 0 : Fin.t 3.
+Check 1 : Fin.t 3.
+Check 2 : Fin.t 3.
+Fail Check 3 : Fin.t 3.
+Unset Printing All.
+
+End Test24.
+
+(* Test number notations for parameterized inductives *)
+Module Test25.
+
+Definition of_uint (u : Number.uint) : list unit :=
+ let fix f n :=
+ match n with
+ | O => nil
+ | S n => cons tt (f n)
+ end in
+ f (Nat.of_num_uint u).
+
+Definition to_uint (l : list unit) : Number.uint :=
+ let fix f n :=
+ match n with
+ | nil => O
+ | cons tt l => S (f l)
+ end in
+ Nat.to_num_uint (f l).
+
+Notation listunit := (list unit) (only parsing).
+Number Notation listunit of_uint to_uint : nat_scope.
+
+Check 0.
+Check 1.
+Check 2.
+
+Check cons tt (cons tt nil).
+Check cons O (cons O nil). (* printer not called on list nat *)
+
+(* inductive with multiple parameters that are not the first
+ parameters and not in the same order for each constructor *)
+Inductive Ip : Type -> Type -> Type :=
+| Ip0 : forall T T', nat -> Ip T T'
+| Ip1 : forall T' T, nat -> Ip T T'
+| Ip2 : forall T, nat -> forall T', Ip T T'
+| Ip3 : nat -> forall T T', Ip T T'.
+
+Definition Ip_of_uint (u : Number.uint) : option (Ip nat bool) :=
+ let f n :=
+ match n with
+ | O => Some (Ip0 nat bool O)
+ | S O => Some (Ip1 bool nat (S O))
+ | S (S O) => Some (Ip2 nat (S (S O)) bool)
+ | S (S (S O)) => Some (Ip3 (S (S (S O))) nat bool)
+ | _ => None
+ end in
+ f (Nat.of_num_uint u).
+
+Definition Ip_to_uint (l : Ip nat bool) : Number.uint :=
+ let f n :=
+ match n with
+ | Ip0 _ _ n => n
+ | Ip1 _ _ n => n
+ | Ip2 _ n _ => n
+ | Ip3 n _ _ => n
+ end in
+ Nat.to_num_uint (f l).
+
+Notation Ip_nat_bool := (Ip nat bool) (only parsing).
+Number Notation Ip_nat_bool Ip_of_uint Ip_to_uint : nat_scope.
+
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Check Ip0 nat bool (S O).
+Check Ip1 bool nat (S O).
+Check Ip2 nat (S O) bool.
+Check Ip3 (S O) nat bool.
+Check Ip0 nat nat (S O). (* not printed *)
+Check Ip0 bool bool (S O). (* not printed *)
+Check Ip1 nat nat (S O). (* not printed *)
+Check Ip3 (S O) nat nat. (* not printed *)
+Set Printing All.
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Unset Printing All.
+
+Notation eqO := (eq _ O) (only parsing).
+Definition eqO_of_uint (x : Number.uint) : eqO := eq_refl O.
+Definition eqO_to_uint (x : O = O) : Number.uint :=
+ match x with
+ | eq_refl _ => Nat.to_num_uint O
+ end.
+Number Notation eqO eqO_of_uint eqO_to_uint : nat_scope.
+
+Check 42.
+Check eq_refl (S O). (* doesn't match eq _ O, printer not called *)
+
+Notation eq_ := (eq _ _) (only parsing).
+Number Notation eq_ eqO_of_uint eqO_to_uint : nat_scope.
+
+Check eq_refl (S O). (* matches eq _ _, printer called *)
+
+Inductive extra_list : Type -> Type :=
+| nil (n : nat) (v : Type) : extra_list v
+| cons (n : nat) (t : Type) (x : t) : extra_list t -> extra_list t.
+
+Definition extra_list_unit_of_uint (x : Number.uint) : extra_list unit :=
+ let fix f n :=
+ match n with
+ | O => nil O unit
+ | S n => cons O unit tt (f n)
+ end in
+ f (Nat.of_num_uint x).
+
+Definition extra_list_unit_to_uint (x : extra_list unit) : Number.uint :=
+ let fix f T (x : extra_list T) :=
+ match x with
+ | nil _ _ => O
+ | cons _ T _ x => S (f T x)
+ end in
+ Nat.to_num_uint (f unit x).
+
+Notation extra_list_unit := (extra_list unit).
+Number Notation extra_list_unit
+ extra_list_unit_of_uint extra_list_unit_to_uint : nat_scope.
+
+Check 2.
+Set Printing All.
+Check 2.
+Unset Printing All.
+
+End Test25.
+
+(* Test the via ... mapping ... option with let-binders, beta-redexes, delta-redexes, etc *)
+Module Test26.
+
+Inductive sum (A : Set) (B : Set) : Set := pair : A -> B -> sum A B.
+
+Inductive I (dummy:=O) :=
+| Iempty : let v := I in id v
+| Iunit : (fun x => x) I
+| Isum : let v := I in (fun A B => A -> B) (let v' := v in v') (forall x : match O with O => I | _ => Empty_set end, let dummy2 := x in I).
+
+Definition of_uint (x : (fun x => let v := I in x) Number.uint) : (fun x => let v := I in x) I :=
+ let fix f n :=
+ match n with
+ | O => Iempty
+ | S O => Iunit
+ | S n => Isum Iunit (f n)
+ end in
+ f (Nat.of_num_uint x).
+
+Definition to_uint (x : (fun x => let v := x in v) I) : match O with O => Number.uint | _ => Empty_set end :=
+ let fix f i :=
+ match i with
+ | Iempty => O
+ | Iunit => 1
+ | Isum i1 i2 => f i1 + f i2
+ end in
+ Nat.to_num_uint (f x).
+
+Notation nSet := (Set) (only parsing). (* needed as a reference is expected in Number Notation and Set is syntactically not a reference *)
+Number Notation nSet of_uint to_uint (via I
+ mapping [Empty_set => Iempty, unit => Iunit, sum => Isum])
+ : type_scope.
+
+Local Open Scope type_scope.
+
+Check Empty_set.
+Check unit.
+Check sum unit unit.
+Check sum unit (sum unit unit).
+Set Printing All.
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Unset Printing All.
+End Test26.
+
+(* Test the via ... mapping ... option with implicit arguments with let binders, etc *)
+Module Test27.
+
+Module Fin.
+Inductive t0 (x:=O) :=
+with
+ t (x:=O) : forall y : nat, let z := y in Set :=
+| F1 (y:=O) {n} : match y with O => t (S n) | _ => Empty_set end
+| FS (y:=x) {n} (v:=n+y) (m:=n) : id (match y with O => id (t n) | _ => Empty_set end -> (fun x => x) t (S m))
+with t' (x:=O) := .
+End Fin.
+
+Inductive I (dummy:=O) :=
+| I1 : I
+| IS : let x := I in id x -> I.
+
+Definition of_uint (x : Number.uint) : I :=
+ let fix f n :=
+ match n with
+ | O => I1
+ | S n => IS (f n)
+ end in
+ f (Nat.of_num_uint x).
+
+Definition to_uint (x : I) : Number.uint :=
+ let fix f i :=
+ match i with
+ | I1 => O
+ | IS n => S (f n)
+ end in
+ Nat.to_num_uint (f x).
+
+Local Open Scope type_scope.
+
+Number Notation Fin.t of_uint to_uint (via I
+ mapping [[Fin.F1] => I1, [Fin.FS] => IS])
+ : type_scope.
+
+Check Fin.F1.
+Check Fin.FS Fin.F1.
+Check Fin.FS (Fin.FS Fin.F1).
+Check Fin.FS (Fin.FS (Fin.FS Fin.F1)).
+Check Fin.F1 : Fin.t 3.
+Check Fin.FS Fin.F1 : Fin.t 3.
+Check Fin.FS (Fin.FS Fin.F1) : Fin.t 3.
+Fail Check Fin.FS (Fin.FS (Fin.FS Fin.F1)) : Fin.t 3.
+Set Printing All.
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Check 0 : Fin.t 3.
+Check 1 : Fin.t 3.
+Check 2 : Fin.t 3.
+Fail Check 3 : Fin.t 3.
+Unset Printing All.
+
+End Test27.
+
+Module Test28.
+Module Fin.
+Inductive t : nat -> Set :=
+| F1 {n : (nat : Set)} : (t (S n) : Set)
+| FS {n : (nat : Set)} : (t n : Set) -> (t (S n) : Set).
+End Fin.
+
+Inductive I :=
+| I1 : I
+| IS : I -> I.
+
+Definition of_uint (x : Number.uint) : I :=
+ let fix f n :=
+ match n with
+ | O => I1
+ | S n => IS (f n)
+ end in
+ f (Nat.of_num_uint x).
+
+Definition to_uint (x : I) : Number.uint :=
+ let fix f i :=
+ match i with
+ | I1 => O
+ | IS n => S (f n)
+ end in
+ Nat.to_num_uint (f x).
+
+Local Open Scope type_scope.
+
+Number Notation Fin.t of_uint to_uint (via I
+ mapping [[Fin.F1] => I1, [Fin.FS] => IS])
+ : type_scope.
+
+Check Fin.F1.
+Check Fin.FS Fin.F1.
+Check Fin.FS (Fin.FS Fin.F1).
+Check Fin.FS (Fin.FS (Fin.FS Fin.F1)).
+Check Fin.F1 : Fin.t 3.
+Check Fin.FS Fin.F1 : Fin.t 3.
+Check Fin.FS (Fin.FS Fin.F1) : Fin.t 3.
+Fail Check Fin.FS (Fin.FS (Fin.FS Fin.F1)) : Fin.t 3.
+Set Printing All.
+Check 0.
+Check 1.
+Check 2.
+Check 3.
+Check 0 : Fin.t 3.
+Check 1 : Fin.t 3.
+Check 2 : Fin.t 3.
+Fail Check 3 : Fin.t 3.
+Unset Printing All.
+
+End Test28.
diff --git a/test-suite/output/QArithSyntax.out b/test-suite/output/QArithSyntax.out
index 9b5c076cb4..ced52524f2 100644
--- a/test-suite/output/QArithSyntax.out
+++ b/test-suite/output/QArithSyntax.out
@@ -1,26 +1,72 @@
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 : 1.02 = 1.02
- : 1.02 = 1.02
-eq_refl : -1e-4 = -1e-4
- : -1e-4 = -1e-4
+1.02e1
+ : Q
+10.2
+ : Q
+1.02e3
+ : Q
+1020
+ : Q
+1.02e2
+ : Q
+102
+ : Q
+eq_refl : 10.2e-1 = 1.02
+ : 10.2e-1 = 1.02
+eq_refl : -0.0001 = -0.0001
+ : -0.0001 = -0.0001
eq_refl : -0.50 = -0.50
: -0.50 = -0.50
-eq_refl : -26 = -26
- : -26 = -26
-eq_refl : 2860 # 256 = 2860 # 256
- : 2860 # 256 = 2860 # 256
-eq_refl : -6882 = -6882
- : -6882 = -6882
-eq_refl : 2860 # 64 = 2860 # 64
- : 2860 # 64 = 2860 # 64
-eq_refl : 2860 = 2860
- : 2860 = 2860
-eq_refl : -2860 # 1024 = -2860 # 1024
- : -2860 # 1024 = -2860 # 1024
+0
+ : Q
+0
+ : Q
+42
+ : Q
+42
+ : Q
+1.23
+ : Q
+0x1.23%xQ
+ : Q
+0.0012
+ : Q
+42e3
+ : Q
+42e-3
+ : Q
+eq_refl : -0x1a = -0x1a
+ : -0x1a = -0x1a
+eq_refl : 0xb.2c = 0xb.2c
+ : 0xb.2c = 0xb.2c
+eq_refl : -0x1ae2 = -0x1ae2
+ : -0x1ae2 = -0x1ae2
+0xb.2cp2
+ : Q
+2860 # 64
+ : Q
+0xb.2cp8
+ : Q
+0xb2c
+ : Q
+eq_refl : -0xb.2cp-2 = -2860 # 1024
+ : -0xb.2cp-2 = -2860 # 1024
+0x0
+ : Q
+0x0
+ : Q
+0x2a
+ : Q
+0x2a
+ : Q
+1.23%Q
+ : Q
+0x1.23
+ : Q
+0x0.0012
+ : Q
+0x2ap3
+ : Q
+0x2ap-3
+ : Q
diff --git a/test-suite/output/QArithSyntax.v b/test-suite/output/QArithSyntax.v
index b5c6222bba..e979abca66 100644
--- a/test-suite/output/QArithSyntax.v
+++ b/test-suite/output/QArithSyntax.v
@@ -1,15 +1,39 @@
Require Import QArith.
Open Scope Q_scope.
Check (eq_refl : 1.02 = 102 # 100).
-Check (eq_refl : 1.02e1 = 102 # 10).
-Check (eq_refl : 1.02e+03 = 1020).
-Check (eq_refl : 1.02e+02 = 102 # 1).
+Check 1.02e1.
+Check 102 # 10.
+Check 1.02e+03.
+Check 1020.
+Check 1.02e+02.
+Check 102 # 1.
Check (eq_refl : 10.2e-1 = 1.02).
Check (eq_refl : -0.0001 = -1 # 10000).
Check (eq_refl : -0.50 = - 50 # 100).
+Check 0.
+Check 000.
+Check 42.
+Check 0x2a.
+Check 1.23.
+Check 0x1.23.
+Check 0.0012.
+Check 42e3.
+Check 42e-3.
+Open Scope hex_Q_scope.
Check (eq_refl : -0x1a = - 26 # 1).
Check (eq_refl : 0xb.2c = 2860 # 256).
Check (eq_refl : -0x1ae2 = -6882).
-Check (eq_refl : 0xb.2cp2 = 2860 # 64).
-Check (eq_refl : 0xb.2cp8 = 2860).
+Check 0xb.2cp2.
+Check 2860 # 64.
+Check 0xb.2cp8.
+Check 2860.
Check (eq_refl : -0xb.2cp-2 = -2860 # 1024).
+Check 0x0.
+Check 0x00.
+Check 42.
+Check 0x2a.
+Check 1.23.
+Check 0x1.23.
+Check 0x0.0012.
+Check 0x2ap3.
+Check 0x2ap-3.
diff --git a/test-suite/output/RealSyntax.out b/test-suite/output/RealSyntax.out
index a9386b2781..a7b7dabb20 100644
--- a/test-suite/output/RealSyntax.out
+++ b/test-suite/output/RealSyntax.out
@@ -4,34 +4,81 @@
: R
1.5%R
: R
-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 : 1.02 = 1.02
- : 1.02 = 1.02
-eq_refl : -1e-4 = -1e-4
- : -1e-4 = -1e-4
-eq_refl : -0.50 = -0.50
- : -0.50 = -0.50
+1.5e1%R
+ : R
+eq_refl : 1.02 = 102e-2
+ : 1.02 = 102e-2
+1.02e1
+ : R
+102e-1
+ : R
+1.02e3
+ : R
+102e1
+ : R
+1.02e2
+ : R
+102
+ : R
+10.2e-1
+ : R
+1.02
+ : R
+eq_refl : -0.0001 = -1e-4
+ : -0.0001 = -1e-4
+eq_refl : -0.50 = -50e-2
+ : -0.50 = -50e-2
eq_refl : -26 = -26
: -26 = -26
-eq_refl : 2860 / IZR (BinIntDef.Z.pow_pos 2 8) = 2860 / IZR (Z.pow_pos 2 8)
- : 2860 / IZR (BinIntDef.Z.pow_pos 2 8) = 2860 / IZR (Z.pow_pos 2 8)
+eq_refl : 0xb.2c%xR = 0xb2cp-8%xR
+ : 0xb.2c%xR = 0xb2cp-8%xR
eq_refl : -6882 = -6882
: -6882 = -6882
-eq_refl : 2860 / IZR (BinIntDef.Z.pow_pos 2 6) = 2860 / IZR (Z.pow_pos 2 6)
- : 2860 / IZR (BinIntDef.Z.pow_pos 2 6) = 2860 / IZR (Z.pow_pos 2 6)
-eq_refl : 2860 = 2860
- : 2860 = 2860
-eq_refl
-:
--2860 / IZR (BinIntDef.Z.pow_pos 2 10) = - (2860) / IZR (Z.pow_pos 2 10)
- : -2860 / IZR (BinIntDef.Z.pow_pos 2 10) =
- - (2860) / IZR (Z.pow_pos 2 10)
+0xb.2cp2%xR
+ : R
+0xb2cp-6%xR
+ : R
+0xb.2cp8%xR
+ : R
+2860
+ : R
+(-0xb.2cp-2)%xR
+ : R
+- 0xb2cp-10%xR
+ : R
+0
+ : R
+0
+ : R
+42
+ : R
+42
+ : R
+1.23
+ : R
+0x1.23%xR
+ : R
+0.0012
+ : R
+42e3
+ : R
+42e-3
+ : R
+0x0
+ : R
+0x0
+ : R
+0x2a
+ : R
+0x2a
+ : R
+1.23%R
+ : R
+0x1.23
+ : R
+0x0.0012
+ : R
+0x2ap3
+ : R
+0x2ap-3
+ : R
diff --git a/test-suite/output/RealSyntax.v b/test-suite/output/RealSyntax.v
index 69ce3ef5f9..790d5c654f 100644
--- a/test-suite/output/RealSyntax.v
+++ b/test-suite/output/RealSyntax.v
@@ -8,18 +8,48 @@ Check 1_.5_e1_%R.
Open Scope R_scope.
Check (eq_refl : 1.02 = IZR 102 / IZR (Z.pow_pos 10 2)).
-Check (eq_refl : 1.02e1 = IZR 102 / IZR (Z.pow_pos 10 1)).
-Check (eq_refl : 1.02e+03 = IZR 102 * IZR (Z.pow_pos 10 1)).
-Check (eq_refl : 1.02e+02 = IZR 102).
-Check (eq_refl : 10.2e-1 = 1.02).
+Check 1.02e1.
+Check IZR 102 / IZR (Z.pow_pos 10 1).
+Check 1.02e+03.
+Check IZR 102 * IZR (Z.pow_pos 10 1).
+Check 1.02e+02.
+Check IZR 102.
+Check 10.2e-1.
+Check 1.02.
Check (eq_refl : -0.0001 = IZR (-1) / IZR (Z.pow_pos 10 4)).
Check (eq_refl : -0.50 = IZR (-50) / IZR (Z.pow_pos 10 2)).
Check (eq_refl : -0x1a = - 26).
Check (eq_refl : 0xb.2c = IZR 2860 / IZR (Z.pow_pos 2 8)).
Check (eq_refl : -0x1ae2 = -6882).
-Check (eq_refl : 0xb.2cp2 = IZR 2860 / IZR (Z.pow_pos 2 6)).
-Check (eq_refl : 0xb.2cp8 = 2860).
-Check (eq_refl : -0xb.2cp-2 = - IZR 2860 / IZR (Z.pow_pos 2 10)).
+Check 0xb.2cp2.
+Check IZR 2860 / IZR (Z.pow_pos 2 6).
+Check 0xb.2cp8.
+Check 2860.
+Check -0xb.2cp-2.
+Check - (IZR 2860 / IZR (Z.pow_pos 2 10)).
+Check 0.
+Check 000.
+Check 42.
+Check 0x2a.
+Check 1.23.
+Check 0x1.23.
+Check 0.0012.
+Check 42e3.
+Check 42e-3.
+
+Open Scope hex_R_scope.
+
+Check 0x0.
+Check 0x000.
+Check 42.
+Check 0x2a.
+Check 1.23.
+Check 0x1.23.
+Check 0x0.0012.
+Check 0x2ap3.
+Check 0x2ap-3.
+
+Close Scope hex_R_scope.
Require Import Reals.
diff --git a/test-suite/output/Search.out b/test-suite/output/Search.out
index 09feca71e7..0f5fd91d93 100644
--- a/test-suite/output/Search.out
+++ b/test-suite/output/Search.out
@@ -30,15 +30,15 @@ implb: bool -> bool -> bool
Nat.odd: nat -> bool
Nat.even: nat -> bool
BoolSpec: Prop -> Prop -> bool -> Prop
-Numeral.numeral_beq: Numeral.numeral -> Numeral.numeral -> bool
+Number.number_beq: Number.number -> Number.number -> bool
Nat.eqb: nat -> nat -> bool
Nat.testbit: nat -> nat -> bool
Decimal.decimal_beq: Decimal.decimal -> Decimal.decimal -> bool
-Numeral.uint_beq: Numeral.uint -> Numeral.uint -> bool
+Number.uint_beq: Number.uint -> Number.uint -> bool
Decimal.uint_beq: Decimal.uint -> Decimal.uint -> bool
Hexadecimal.hexadecimal_beq:
Hexadecimal.hexadecimal -> Hexadecimal.hexadecimal -> bool
-Numeral.int_beq: Numeral.int -> Numeral.int -> bool
+Number.int_beq: Number.int -> Number.int -> bool
Hexadecimal.uint_beq: Hexadecimal.uint -> Hexadecimal.uint -> bool
Nat.ltb: nat -> nat -> bool
Nat.leb: nat -> nat -> bool
@@ -64,34 +64,34 @@ eq_true_rec:
bool_ind: forall P : bool -> Prop, P true -> P false -> forall b : bool, P b
eq_true_sind:
forall P : bool -> SProp, P true -> forall b : bool, eq_true b -> P b
-Numeral.internal_uint_dec_bl1:
- forall x y : Numeral.uint, Numeral.uint_beq x y = true -> x = y
+Number.internal_uint_dec_bl1:
+ forall x y : Number.uint, Number.uint_beq x y = true -> x = y
Hexadecimal.internal_hexadecimal_dec_lb:
forall x y : Hexadecimal.hexadecimal,
x = y -> Hexadecimal.hexadecimal_beq x y = true
Hexadecimal.internal_int_dec_lb0:
forall x y : Hexadecimal.int, x = y -> Hexadecimal.int_beq x y = true
-Numeral.internal_numeral_dec_lb:
- forall x y : Numeral.numeral, x = y -> Numeral.numeral_beq x y = true
+Number.internal_number_dec_lb:
+ forall x y : Number.number, x = y -> Number.number_beq x y = true
Decimal.internal_decimal_dec_lb:
forall x y : Decimal.decimal, x = y -> Decimal.decimal_beq x y = true
Hexadecimal.internal_int_dec_bl0:
forall x y : Hexadecimal.int, Hexadecimal.int_beq x y = true -> x = y
-Numeral.internal_int_dec_lb1:
- forall x y : Numeral.int, x = y -> Numeral.int_beq x y = true
-Numeral.internal_int_dec_bl1:
- forall x y : Numeral.int, Numeral.int_beq x y = true -> x = y
+Number.internal_int_dec_lb1:
+ forall x y : Number.int, x = y -> Number.int_beq x y = true
+Number.internal_int_dec_bl1:
+ forall x y : Number.int, Number.int_beq x y = true -> x = y
Hexadecimal.internal_hexadecimal_dec_bl:
forall x y : Hexadecimal.hexadecimal,
Hexadecimal.hexadecimal_beq x y = true -> x = y
-Numeral.internal_uint_dec_lb1:
- forall x y : Numeral.uint, x = y -> Numeral.uint_beq x y = true
+Number.internal_uint_dec_lb1:
+ forall x y : Number.uint, x = y -> Number.uint_beq x y = true
Decimal.internal_int_dec_bl:
forall x y : Decimal.int, Decimal.int_beq x y = true -> x = y
Decimal.internal_int_dec_lb:
forall x y : Decimal.int, x = y -> Decimal.int_beq x y = true
-Numeral.internal_numeral_dec_bl:
- forall x y : Numeral.numeral, Numeral.numeral_beq x y = true -> x = y
+Number.internal_number_dec_bl:
+ forall x y : Number.number, Number.number_beq x y = true -> x = y
Byte.of_bits:
bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))) ->
Byte.byte
@@ -160,21 +160,21 @@ f_equal2_mult:
f_equal2_nat:
forall (B : Type) (f : nat -> nat -> B) (x1 y1 x2 y2 : nat),
x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2
-Numeral.internal_numeral_dec_lb:
- forall x y : Numeral.numeral, x = y -> Numeral.numeral_beq x y = true
-Numeral.internal_int_dec_lb1:
- forall x y : Numeral.int, x = y -> Numeral.int_beq x y = true
-Numeral.internal_numeral_dec_bl:
- forall x y : Numeral.numeral, Numeral.numeral_beq x y = true -> x = y
+Number.internal_number_dec_lb:
+ forall x y : Number.number, x = y -> Number.number_beq x y = true
+Number.internal_int_dec_lb1:
+ forall x y : Number.int, x = y -> Number.int_beq x y = true
+Number.internal_number_dec_bl:
+ forall x y : Number.number, Number.number_beq x y = true -> x = y
Hexadecimal.internal_hexadecimal_dec_lb:
forall x y : Hexadecimal.hexadecimal,
x = y -> Hexadecimal.hexadecimal_beq x y = true
-Numeral.internal_int_dec_bl1:
- forall x y : Numeral.int, Numeral.int_beq x y = true -> x = y
-Numeral.internal_uint_dec_lb1:
- forall x y : Numeral.uint, x = y -> Numeral.uint_beq x y = true
-Numeral.internal_uint_dec_bl1:
- forall x y : Numeral.uint, Numeral.uint_beq x y = true -> x = y
+Number.internal_int_dec_bl1:
+ forall x y : Number.int, Number.int_beq x y = true -> x = y
+Number.internal_uint_dec_lb1:
+ forall x y : Number.uint, x = y -> Number.uint_beq x y = true
+Number.internal_uint_dec_bl1:
+ forall x y : Number.uint, Number.uint_beq x y = true -> x = y
Decimal.internal_decimal_dec_lb:
forall x y : Decimal.decimal, x = y -> Decimal.decimal_beq x y = true
Hexadecimal.internal_hexadecimal_dec_bl:
@@ -213,18 +213,18 @@ bool_choice:
forall [S : Set] [R1 R2 : S -> Prop],
(forall x : S, {R1 x} + {R2 x}) ->
{f : S -> bool | forall x : S, f x = true /\ R1 x \/ f x = false /\ R2 x}
-Numeral.internal_numeral_dec_lb:
- forall x y : Numeral.numeral, x = y -> Numeral.numeral_beq x y = true
-Numeral.internal_numeral_dec_bl:
- forall x y : Numeral.numeral, Numeral.numeral_beq x y = true -> x = y
-Numeral.internal_int_dec_lb1:
- forall x y : Numeral.int, x = y -> Numeral.int_beq x y = true
-Numeral.internal_int_dec_bl1:
- forall x y : Numeral.int, Numeral.int_beq x y = true -> x = y
-Numeral.internal_uint_dec_lb1:
- forall x y : Numeral.uint, x = y -> Numeral.uint_beq x y = true
-Numeral.internal_uint_dec_bl1:
- forall x y : Numeral.uint, Numeral.uint_beq x y = true -> x = y
+Number.internal_number_dec_lb:
+ forall x y : Number.number, x = y -> Number.number_beq x y = true
+Number.internal_number_dec_bl:
+ forall x y : Number.number, Number.number_beq x y = true -> x = y
+Number.internal_int_dec_lb1:
+ forall x y : Number.int, x = y -> Number.int_beq x y = true
+Number.internal_int_dec_bl1:
+ forall x y : Number.int, Number.int_beq x y = true -> x = y
+Number.internal_uint_dec_lb1:
+ forall x y : Number.uint, x = y -> Number.uint_beq x y = true
+Number.internal_uint_dec_bl1:
+ forall x y : Number.uint, Number.uint_beq x y = true -> x = y
Hexadecimal.internal_hexadecimal_dec_lb:
forall x y : Hexadecimal.hexadecimal,
x = y -> Hexadecimal.hexadecimal_beq x y = true
@@ -306,12 +306,12 @@ nat_rect_plus:
(nat_rect (fun _ : nat => A) x (fun _ : nat => f) m)
(fun _ : nat => f) n
Nat.bitwise: (bool -> bool -> bool) -> nat -> nat -> nat -> nat
-Numeral.internal_numeral_dec_bl:
- forall x y : Numeral.numeral, Numeral.numeral_beq x y = true -> x = y
-Numeral.internal_int_dec_bl1:
- forall x y : Numeral.int, Numeral.int_beq x y = true -> x = y
-Numeral.internal_uint_dec_bl1:
- forall x y : Numeral.uint, Numeral.uint_beq x y = true -> x = y
+Number.internal_number_dec_bl:
+ forall x y : Number.number, Number.number_beq x y = true -> x = y
+Number.internal_int_dec_bl1:
+ forall x y : Number.int, Number.int_beq x y = true -> x = y
+Number.internal_uint_dec_bl1:
+ forall x y : Number.uint, Number.uint_beq x y = true -> x = y
Hexadecimal.internal_hexadecimal_dec_bl:
forall x y : Hexadecimal.hexadecimal,
Hexadecimal.hexadecimal_beq x y = true -> x = y
@@ -328,12 +328,12 @@ Byte.to_bits_of_bits:
forall
b : bool * (bool * (bool * (bool * (bool * (bool * (bool * bool)))))),
Byte.to_bits (Byte.of_bits b) = b
-Numeral.internal_numeral_dec_lb:
- forall x y : Numeral.numeral, x = y -> Numeral.numeral_beq x y = true
-Numeral.internal_uint_dec_lb1:
- forall x y : Numeral.uint, x = y -> Numeral.uint_beq x y = true
-Numeral.internal_int_dec_lb1:
- forall x y : Numeral.int, x = y -> Numeral.int_beq x y = true
+Number.internal_number_dec_lb:
+ forall x y : Number.number, x = y -> Number.number_beq x y = true
+Number.internal_uint_dec_lb1:
+ forall x y : Number.uint, x = y -> Number.uint_beq x y = true
+Number.internal_int_dec_lb1:
+ forall x y : Number.int, x = y -> Number.int_beq x y = true
Decimal.internal_int_dec_lb:
forall x y : Decimal.int, x = y -> Decimal.int_beq x y = true
Hexadecimal.internal_hexadecimal_dec_lb:
@@ -391,7 +391,7 @@ Nat.lor: nat -> nat -> nat
Nat.lxor: nat -> nat -> nat
Nat.of_hex_uint: Hexadecimal.uint -> nat
Nat.of_uint: Decimal.uint -> nat
-Nat.of_num_uint: Numeral.uint -> nat
+Nat.of_num_uint: Number.uint -> nat
length: forall [A : Type], list A -> nat
plus_n_O: forall n : nat, n = n + 0
plus_O_n: forall n : nat, 0 + n = n
@@ -458,3 +458,11 @@ reflexive_eq_dom_reflexive:
B.b: B.a
A.b: A.a
F.L: F.P 0
+inr: forall {A B : Type}, B -> A + B
+inl: forall {A B : Type}, A -> A + B
+(use "About" for full details on the implicit arguments of inl and inr)
+f: None = 0
+partition_cons1:
+ forall [A : Type] (f : A -> bool) (a : A) (l : list A) [l1 l2 : list A],
+ partition f l = (l1, l2) ->
+ f a = true -> partition f (a :: l) = (a :: l1, l2)
diff --git a/test-suite/output/Search.v b/test-suite/output/Search.v
index a5ac2cb511..3419d5ac62 100644
--- a/test-suite/output/Search.v
+++ b/test-suite/output/Search.v
@@ -89,3 +89,16 @@ Module Bug12647.
Search F.P.
End Bar.
End Bug12647.
+
+Module WithCoercions.
+ Search headconcl:(_ + _) inside Datatypes.
+ Coercion Some_nat := @Some nat.
+ Axiom f : None = 0.
+ Search (None = 0).
+End WithCoercions.
+
+Require Import List.
+
+Module Wish13349.
+Search partition "1" inside List.
+End Wish13349.
diff --git a/test-suite/output/SearchHead.out b/test-suite/output/SearchHead.out
index 9554581ebe..2f0d854ac6 100644
--- a/test-suite/output/SearchHead.out
+++ b/test-suite/output/SearchHead.out
@@ -21,15 +21,15 @@ orb: bool -> bool -> bool
implb: bool -> bool -> bool
Nat.odd: nat -> bool
Nat.even: nat -> bool
-Numeral.uint_beq: Numeral.uint -> Numeral.uint -> bool
+Number.uint_beq: Number.uint -> Number.uint -> bool
Nat.testbit: nat -> nat -> bool
Nat.eqb: nat -> nat -> bool
Hexadecimal.hexadecimal_beq:
Hexadecimal.hexadecimal -> Hexadecimal.hexadecimal -> bool
Nat.ltb: nat -> nat -> bool
Nat.leb: nat -> nat -> bool
-Numeral.numeral_beq: Numeral.numeral -> Numeral.numeral -> bool
-Numeral.int_beq: Numeral.int -> Numeral.int -> bool
+Number.number_beq: Number.number -> Number.number -> bool
+Number.int_beq: Number.int -> Number.int -> bool
Hexadecimal.int_beq: Hexadecimal.int -> Hexadecimal.int -> bool
Hexadecimal.uint_beq: Hexadecimal.uint -> Hexadecimal.uint -> bool
Decimal.decimal_beq: Decimal.decimal -> Decimal.decimal -> bool
diff --git a/test-suite/output/SearchPattern.out b/test-suite/output/SearchPattern.out
index 80b03e8a0b..d705ec898b 100644
--- a/test-suite/output/SearchPattern.out
+++ b/test-suite/output/SearchPattern.out
@@ -7,15 +7,15 @@ orb: bool -> bool -> bool
implb: bool -> bool -> bool
Nat.odd: nat -> bool
Nat.even: nat -> bool
-Numeral.uint_beq: Numeral.uint -> Numeral.uint -> bool
+Number.uint_beq: Number.uint -> Number.uint -> bool
Nat.testbit: nat -> nat -> bool
Nat.eqb: nat -> nat -> bool
Hexadecimal.hexadecimal_beq:
Hexadecimal.hexadecimal -> Hexadecimal.hexadecimal -> bool
Nat.ltb: nat -> nat -> bool
Nat.leb: nat -> nat -> bool
-Numeral.numeral_beq: Numeral.numeral -> Numeral.numeral -> bool
-Numeral.int_beq: Numeral.int -> Numeral.int -> bool
+Number.number_beq: Number.number -> Number.number -> bool
+Number.int_beq: Number.int -> Number.int -> bool
Hexadecimal.int_beq: Hexadecimal.int -> Hexadecimal.int -> bool
Hexadecimal.uint_beq: Hexadecimal.uint -> Hexadecimal.uint -> bool
Decimal.decimal_beq: Decimal.decimal -> Decimal.decimal -> bool
@@ -50,7 +50,7 @@ Nat.lor: nat -> nat -> nat
Nat.gcd: nat -> nat -> nat
Hexadecimal.nb_digits: Hexadecimal.uint -> nat
Nat.of_hex_uint: Hexadecimal.uint -> nat
-Nat.of_num_uint: Numeral.uint -> nat
+Nat.of_num_uint: Number.uint -> nat
Nat.of_uint: Decimal.uint -> nat
Decimal.nb_digits: Decimal.uint -> nat
Nat.tail_addmul: nat -> nat -> nat -> nat
diff --git a/test-suite/output/Search_bug13298.out b/test-suite/output/Search_bug13298.out
new file mode 100644
index 0000000000..18488c790f
--- /dev/null
+++ b/test-suite/output/Search_bug13298.out
@@ -0,0 +1 @@
+snd: forall c : c, fst c = 0
diff --git a/test-suite/output/Search_bug13298.v b/test-suite/output/Search_bug13298.v
new file mode 100644
index 0000000000..9a75321c64
--- /dev/null
+++ b/test-suite/output/Search_bug13298.v
@@ -0,0 +1,3 @@
+Set Primitive Projections.
+Record c : Type := { fst : nat; snd : fst = 0 }.
+Search concl:fst.
diff --git a/test-suite/output/StringSyntax.out b/test-suite/output/StringSyntax.out
index e9cf4282dc..68ee7cfeb5 100644
--- a/test-suite/output/StringSyntax.out
+++ b/test-suite/output/StringSyntax.out
@@ -1051,7 +1051,7 @@ Arguments byte_ind _%function_scope _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
"127"
: byte
The command has indeed failed with message:
-Expects a single character or a three-digits ascii code.
+Expects a single character or a three-digit ASCII code.
"000"
: ascii
"a"
@@ -1059,7 +1059,7 @@ Expects a single character or a three-digits ascii code.
"127"
: ascii
The command has indeed failed with message:
-Expects a single character or a three-digits ascii code.
+Expects a single character or a three-digit ASCII code.
"000"
: string
"a"
@@ -1084,3 +1084,21 @@ Expects a single character or a three-digits ascii code.
= ["000"; "001"; "002"; "003"; "004"; "005"; "006"; "007"; "008"; "009"; "010"; "011"; "012"; "013"; "014"; "015"; "016"; "017"; "018"; "019"; "020"; "021"; "022"; "023"; "024"; "025"; "026"; "027"; "028"; "029"; "030"; "031"; " "; "!"; """"; "#"; "$"; "%"; "&"; "'"; "("; ")"; "*"; "+"; ","; "-"; "."; "/"; "0"; "1"; "2"; "3"; "4"; "5"; "6"; "7"; "8"; "9"; ":"; ";"; "<"; "="; ">"; "?"; "@"; "A"; "B"; "C"; "D"; "E"; "F"; "G"; "H"; "I"; "J"; "K"; "L"; "M"; "N"; "O"; "P"; "Q"; "R"; "S"; "T"; "U"; "V"; "W"; "X"; "Y"; "Z"; "["; "\"; "]"; "^"; "_"; "`"; "a"; "b"; "c"; "d"; "e"; "f"; "g"; "h"; "i"; "j"; "k"; "l"; "m"; "n"; "o"; "p"; "q"; "r"; "s"; "t"; "u"; "v"; "w"; "x"; "y"; "z"; "{"; "|"; "}"; "~"; "127"; "128"; "129"; "130"; "131"; "132"; "133"; "134"; "135"; "136"; "137"; "138"; "139"; "140"; "141"; "142"; "143"; "144"; "145"; "146"; "147"; "148"; "149"; "150"; "151"; "152"; "153"; "154"; "155"; "156"; "157"; "158"; "159"; "160"; "161"; "162"; "163"; "164"; "165"; "166"; "167";
"168"; "169"; "170"; "171"; "172"; "173"; "174"; "175"; "176"; "177"; "178"; "179"; "180"; "181"; "182"; "183"; "184"; "185"; "186"; "187"; "188"; "189"; "190"; "191"; "192"; "193"; "194"; "195"; "196"; "197"; "198"; "199"; "200"; "201"; "202"; "203"; "204"; "205"; "206"; "207"; "208"; "209"; "210"; "211"; "212"; "213"; "214"; "215"; "216"; "217"; "218"; "219"; "220"; "221"; "222"; "223"; "224"; "225"; "226"; "227"; "228"; "229"; "230"; "231"; "232"; "233"; "234"; "235"; "236"; "237"; "238"; "239"; "240"; "241"; "242"; "243"; "244"; "245"; "246"; "247"; "248"; "249"; "250"; "251"; "252"; "253"; "254"; "255"]
: list ascii
+"abc"
+ : string
+"000"
+ : nat
+"001"
+ : nat
+"002"
+ : nat
+"255"
+ : nat
+The command has indeed failed with message:
+Expects a single character or a three-digit ASCII code.
+"abc"
+ : string2
+"abc" : string2
+ : string2
+"abc" : string1
+ : string1
diff --git a/test-suite/output/StringSyntax.v b/test-suite/output/StringSyntax.v
index aab6e0bb03..a1ffe69527 100644
--- a/test-suite/output/StringSyntax.v
+++ b/test-suite/output/StringSyntax.v
@@ -50,3 +50,68 @@ Local Close Scope byte_scope.
Local Open Scope char_scope.
Compute List.map Ascii.ascii_of_nat (List.seq 0 256).
Local Close Scope char_scope.
+
+(* Test numeral notations for parameterized inductives *)
+Module Test2.
+
+Notation string := (list Byte.byte).
+Definition id_string := @id string.
+
+String Notation string id_string id_string : list_scope.
+
+Check "abc"%list.
+
+End Test2.
+
+(* Test the via ... using ... option *)
+Module Test3.
+
+Inductive I :=
+| IO : I
+| IS : I -> I.
+
+Definition of_byte (x : Byte.byte) : I :=
+ let fix f n :=
+ match n with
+ | O => IO
+ | S n => IS (f n)
+ end in
+ f (Byte.to_nat x).
+
+Definition to_byte (x : I) : option Byte.byte :=
+ let fix f i :=
+ match i with
+ | IO => O
+ | IS i => S (f i)
+ end in
+ Byte.of_nat (f x).
+
+String Notation nat of_byte to_byte (via I mapping [O => IO, S => IS]) : nat_scope.
+
+Check "000".
+Check "001".
+Check "002".
+Check "255".
+Fail Check "256".
+
+End Test3.
+
+(* Test overlapping string notations *)
+Module Test4.
+
+Notation string1 := (list Byte.byte).
+Definition id_string1 := @id string1.
+
+String Notation string1 id_string1 id_string1 : list_scope.
+
+Notation string2 := (list Ascii.ascii).
+Definition a2b := List.map byte_of_ascii.
+Definition b2a := List.map ascii_of_byte.
+
+String Notation string2 b2a a2b : list_scope.
+
+Check "abc"%list.
+Check ["a";"b";"c"]%char%list : string2.
+Check ["a";"b";"c"]%byte%list : string1.
+
+End Test4.
diff --git a/test-suite/output/ZSyntax.v b/test-suite/output/ZSyntax.v
index 7b2bb00ce0..67c4f85d5c 100644
--- a/test-suite/output/ZSyntax.v
+++ b/test-suite/output/ZSyntax.v
@@ -18,7 +18,7 @@ Require Import Arith.
Check (0 + Z.of_nat 11)%Z.
(* Check hexadecimal printing *)
-Definition to_num_int n := Numeral.IntHex (Z.to_hex_int n).
+Definition to_num_int n := Number.IntHexadecimal (Z.to_hex_int n).
Number Notation Z Z.of_num_int to_num_int : Z_scope.
Check 42%Z.
Check (-42)%Z.
diff --git a/test-suite/output/bug_12159.v b/test-suite/output/bug_12159.v
index 437b4a68e9..a7366f2d35 100644
--- a/test-suite/output/bug_12159.v
+++ b/test-suite/output/bug_12159.v
@@ -2,10 +2,10 @@ Declare Scope A.
Declare Scope B.
Delimit Scope A with A.
Delimit Scope B with B.
-Definition to_unit (v : Numeral.uint) : option unit
+Definition to_unit (v : Number.uint) : option unit
:= match Nat.of_num_uint v with O => Some tt | _ => None end.
-Definition of_unit (v : unit) : Numeral.uint := Nat.to_num_uint 0.
-Definition of_unit' (v : unit) : Numeral.uint := Nat.to_num_uint 1.
+Definition of_unit (v : unit) : Number.uint := Nat.to_num_uint 0.
+Definition of_unit' (v : unit) : Number.uint := Nat.to_num_uint 1.
Number Notation unit to_unit of_unit : A.
Number Notation unit to_unit of_unit' : B.
Definition f x : unit := x.
diff --git a/test-suite/output/bug_13004.out b/test-suite/output/bug_13004.out
index 2bd7d67535..28bc580202 100644
--- a/test-suite/output/bug_13004.out
+++ b/test-suite/output/bug_13004.out
@@ -1,2 +1,2 @@
-Ltac bug_13004.t := ltac2:(print (of_string "hi"))
-Ltac bug_13004.u := ident:(H)
+Ltac t := ltac2:(print (of_string "hi"))
+Ltac u := ident:(H)
diff --git a/test-suite/output/bug_13238.out b/test-suite/output/bug_13238.out
index bda21aa9e3..a17d05200d 100644
--- a/test-suite/output/bug_13238.out
+++ b/test-suite/output/bug_13238.out
@@ -1,4 +1,4 @@
-Ltac bug_13238.t1 x := replace (x x) with (x x)
-Ltac bug_13238.t2 x := case : x
-Ltac bug_13238.t3 := by move ->
-Ltac bug_13238.t4 := congr True
+Ltac t1 x := replace (x x) with (x x)
+Ltac t2 x := case : x
+Ltac t3 := by move ->
+Ltac t4 := congr True
diff --git a/test-suite/output/bug_13244.out b/test-suite/output/bug_13244.out
new file mode 100644
index 0000000000..8c7d4ac776
--- /dev/null
+++ b/test-suite/output/bug_13244.out
@@ -0,0 +1,9 @@
+negbT: forall [b : bool], b = false -> ~~ b
+contra_notN: forall [P : Prop] [b : bool], (b -> P) -> ~ P -> ~~ b
+contraPN: forall [P : Prop] [b : bool], (b -> ~ P) -> P -> ~~ b
+contraNN: forall [c b : bool], (c -> b) -> ~~ b -> ~~ c
+contraL: forall [c b : bool], (c -> ~~ b) -> b -> ~~ c
+contraTN: forall [c b : bool], (c -> ~~ b) -> b -> ~~ c
+contra: forall [c b : bool], (c -> b) -> ~~ b -> ~~ c
+introN: forall [P : Prop] [b : bool], reflect P b -> ~ P -> ~~ b
+contraFN: forall [c b : bool], (c -> b) -> b = false -> ~~ c
diff --git a/test-suite/output/bug_13244.v b/test-suite/output/bug_13244.v
new file mode 100644
index 0000000000..83eaac1a35
--- /dev/null
+++ b/test-suite/output/bug_13244.v
@@ -0,0 +1,3 @@
+Require Import ssr.ssrbool.
+Set Warnings "-ssr-search-moved".
+Search headconcl:(~~ _).
diff --git a/test-suite/output/bug_13320.out b/test-suite/output/bug_13320.out
new file mode 100644
index 0000000000..97efe1da87
--- /dev/null
+++ b/test-suite/output/bug_13320.out
@@ -0,0 +1,2 @@
+The command has indeed failed with message:
+No obligations remaining
diff --git a/test-suite/output/bug_13320.v b/test-suite/output/bug_13320.v
new file mode 100644
index 0000000000..6f3c51bbe7
--- /dev/null
+++ b/test-suite/output/bug_13320.v
@@ -0,0 +1,2 @@
+(* Next Obligation should fail normally, not with an anomaly. *)
+Fail Next Obligation.
diff --git a/test-suite/output/prim_array.out b/test-suite/output/prim_array.out
new file mode 100644
index 0000000000..6c12153ab9
--- /dev/null
+++ b/test-suite/output/prim_array.out
@@ -0,0 +1,9 @@
+[| | 0 : nat |]
+ : array nat
+[| 1; 2; 3 | 0 : nat |]
+ : array nat
+[| | 0 : nat |]@{Set}
+ : array@{Set} nat
+[| bool; list nat | nat : Set |]@{prim_array.4}
+ : array@{prim_array.4} Set
+(* {prim_array.4} |= Set < prim_array.4 *)
diff --git a/test-suite/output/prim_array.v b/test-suite/output/prim_array.v
new file mode 100644
index 0000000000..a82f6a16f1
--- /dev/null
+++ b/test-suite/output/prim_array.v
@@ -0,0 +1,10 @@
+Primitive array := #array_type.
+
+Check [| | 0 |].
+
+Check [| 1; 2; 3 | 0 |].
+
+Set Printing Universes.
+Check [| | 0 |].
+
+Check [| bool; list nat | nat |].
diff --git a/test-suite/report.sh b/test-suite/report.sh
index 5b74bee0c7..0b8497b809 100755
--- a/test-suite/report.sh
+++ b/test-suite/report.sh
@@ -21,7 +21,7 @@ cp summary.log "$SAVEDIR"/
rm "$FAILED"
# print info
-if [ -n "$APPVEYOR" ] || [ -n "$PRINT_LOGS" ]; then
+if [ -n "$CI" ] || [ -n "$PRINT_LOGS" ]; then
find logs/ -name '*.log' -not -name 'summary.log' -print0 | while IFS= read -r -d '' file; do
printf '%s\n' "$file"
cat "$file"
diff --git a/test-suite/ssr/ipat_apply.v b/test-suite/ssr/ipat_apply.v
new file mode 100644
index 0000000000..2f7986aea6
--- /dev/null
+++ b/test-suite/ssr/ipat_apply.v
@@ -0,0 +1,13 @@
+Require Import ssreflect.
+
+Section Apply.
+
+Variable P : nat -> Prop.
+Lemma test_apply A B : forall (f : A -> B) (a : A), B.
+
+Proof.
+move=> /[apply] b.
+exact.
+Qed.
+
+End Apply.
diff --git a/test-suite/ssr/ipat_dup.v b/test-suite/ssr/ipat_dup.v
new file mode 100644
index 0000000000..b1936df31d
--- /dev/null
+++ b/test-suite/ssr/ipat_dup.v
@@ -0,0 +1,13 @@
+Require Import ssreflect.
+
+Section Dup.
+
+Variable P : nat -> Prop.
+
+Lemma test_dup1 : forall n : nat, P n.
+Proof. move=> /[dup] m n; suff: P n by []. Abort.
+
+Lemma test_dup2 : let n := 1 in False.
+Proof. move=> /[dup] m n; have : m = n := eq_refl. Abort.
+
+End Dup.
diff --git a/test-suite/ssr/ipat_swap.v b/test-suite/ssr/ipat_swap.v
new file mode 100644
index 0000000000..1d78a2a009
--- /dev/null
+++ b/test-suite/ssr/ipat_swap.v
@@ -0,0 +1,13 @@
+Require Import ssreflect.
+
+Section Swap.
+
+Definition P n := match n with 1 => true | _ => false end.
+
+Lemma test_swap1 : forall (n : nat) (b : bool), P n = b.
+Proof. move=> /[swap] b n; suff: P n = b by []. Abort.
+
+Lemma test_swap1 : let n := 1 in let b := true in False.
+Proof. move=> /[swap] b n; have : P n = b := eq_refl. Abort.
+
+End Swap.
diff --git a/test-suite/success/CompatOldOldFlag.v b/test-suite/success/CompatOldOldFlag.v
deleted file mode 100644
index f408e95d2e..0000000000
--- a/test-suite/success/CompatOldOldFlag.v
+++ /dev/null
@@ -1,6 +0,0 @@
-(* -*- coq-prog-args: ("-compat" "8.10") -*- *)
-(** Check that the current-minus-three compatibility flag actually requires the relevant modules. *)
-Import Coq.Compat.Coq813.
-Import Coq.Compat.Coq812.
-Import Coq.Compat.Coq811.
-Import Coq.Compat.Coq810.
diff --git a/test-suite/success/NumeralNotationsNoLocal.v b/test-suite/success/NumberNotationsNoLocal.v
index fe97f10ddf..e19d06cfa7 100644
--- a/test-suite/success/NumeralNotationsNoLocal.v
+++ b/test-suite/success/NumberNotationsNoLocal.v
@@ -1,4 +1,4 @@
-(* Test that numeral notations don't work on proof-local variables, especially not ones containing evars *)
+(* Test that number notations don't work on proof-local variables, especially not ones containing evars *)
Inductive unit11 := tt11.
Declare Scope unit11_scope.
Delimit Scope unit11_scope with unit11.
diff --git a/test-suite/success/definition_using.v b/test-suite/success/definition_using.v
new file mode 100644
index 0000000000..120e62b145
--- /dev/null
+++ b/test-suite/success/definition_using.v
@@ -0,0 +1,68 @@
+Require Import Program.
+Axiom bogus : Type.
+
+Section A.
+Variable x : bogus.
+
+#[using="All"]
+Definition c1 : bool := true.
+
+#[using="All"]
+Fixpoint c2 n : bool :=
+ match n with
+ | O => true
+ | S p => c3 p
+ end
+with c3 n : bool :=
+ match n with
+ | O => true
+ | S p => c2 p
+end.
+
+#[using="All"]
+Definition c4 : bool. Proof. exact true. Qed.
+
+#[using="All"]
+Fixpoint c5 (n : nat) {struct n} : bool. Proof. destruct n as [|p]. exact true. exact (c5 p). Qed.
+
+#[using="All", program]
+Definition c6 : bool. Proof. exact true. Qed.
+
+#[using="All", program]
+Fixpoint c7 (n : nat) {struct n} : bool :=
+ match n with
+ | O => true
+ | S p => c7 p
+ end.
+
+End A.
+
+Check c1 : bogus -> bool.
+Check c2 : bogus -> nat -> bool.
+Check c3 : bogus -> nat -> bool.
+Check c4 : bogus -> bool.
+Check c5 : bogus -> nat -> bool.
+Check c6 : bogus -> bool.
+Check c7 : bogus -> nat -> bool.
+
+Section B.
+
+Variable a : bogus.
+Variable h : c1 a = true.
+
+#[using="a*"]
+Definition c8 : bogus := a.
+
+Collection ccc := a h.
+
+#[using="ccc"]
+Definition c9 : bogus := a.
+
+#[using="ccc - h"]
+Definition c10 : bogus := a.
+
+End B.
+
+Check c8 : forall a, c1 a = true -> bogus.
+Check c9 : forall a, c1 a = true -> bogus.
+Check c10: bogus -> bogus.
diff --git a/test-suite/success/proof_using_noinit.v b/test-suite/success/proof_using_noinit.v
new file mode 100644
index 0000000000..f99b49619c
--- /dev/null
+++ b/test-suite/success/proof_using_noinit.v
@@ -0,0 +1,9 @@
+(* -*- coq-prog-args: ("-noinit"); -*- *)
+
+Section A.
+Variable A : Prop.
+Hypothesis a : A.
+Lemma b : A.
+Proof using a.
+Admitted.
+End A.
diff --git a/test-suite/success/rewrite_strat.v b/test-suite/success/rewrite_strat.v
index a6e59fdda0..98045d1162 100644
--- a/test-suite/success/rewrite_strat.v
+++ b/test-suite/success/rewrite_strat.v
@@ -51,3 +51,12 @@ Time Qed. (* 0.06 s *)
Set Printing All.
Set Printing Depth 100000.
+
+Tactic Notation "my_rewrite_strat" constr(x) := rewrite_strat topdown x.
+Tactic Notation "my_rewrite_strat2" uconstr(x) := rewrite_strat topdown x.
+Goal (forall x, S x = 0) -> 1=0.
+intro H.
+my_rewrite_strat H.
+Undo.
+my_rewrite_strat2 H.
+Abort.
diff --git a/test-suite/success/sprop_uip.v b/test-suite/success/sprop_uip.v
index eae1b75689..c9377727db 100644
--- a/test-suite/success/sprop_uip.v
+++ b/test-suite/success/sprop_uip.v
@@ -121,6 +121,33 @@ Proof.
simpl. Fail check.
Abort.
+Module HoTTStyle.
+ (* a small proof which tests destruct in a tricky case *)
+
+ Definition ap {A B} (f:A -> B) {x y} (e : seq x y) : seq (f x) (f y).
+ Proof. destruct e. reflexivity. Defined.
+
+ Section S.
+ Context
+ (A : Type)
+ (B : Type)
+ (f : A -> B)
+ (g : B -> A)
+ (section : forall a, seq (g (f a)) a)
+ (retraction : forall b, seq (f (g b)) b).
+
+ Lemma bla (P : B -> Type) (a : A) (F : forall a, P (f a))
+ : seq_rect _ (f (g (f a))) (fun a _ => P a) (F (g (f a))) (f a) (retraction (f a)) = F a.
+ Proof.
+ lazy.
+ change (retraction (f a)) with (ap f (section a)).
+ destruct (section a).
+ reflexivity.
+ Qed.
+ End S.
+
+End HoTTStyle.
+
(* check that extraction doesn't fall apart on matches with special reduction *)
Require Extraction.
diff --git a/test-suite/tools/update-compat/run.sh b/test-suite/tools/update-compat/run.sh
index 61273c4f37..7ff5571ffb 100755
--- a/test-suite/tools/update-compat/run.sh
+++ b/test-suite/tools/update-compat/run.sh
@@ -6,4 +6,4 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
# we assume that the script lives in test-suite/tools/update-compat/,
# and that update-compat.py lives in dev/tools/
cd "${SCRIPT_DIR}/../../.."
-dev/tools/update-compat.py --assert-unchanged --master || exit $?
+dev/tools/update-compat.py --assert-unchanged --release || exit $?
diff --git a/theories/Arith/Div2.v b/theories/Arith/Div2.v
index 36b9cf06b9..2d34412908 100644
--- a/theories/Arith/Div2.v
+++ b/theories/Arith/Div2.v
@@ -31,7 +31,7 @@ Lemma ind_0_1_SS :
Proof.
intros P H0 H1 H2.
fix ind_0_1_SS 1.
- destruct n as [|[|n]].
+ intros n; destruct n as [|[|n]].
- exact H0.
- exact H1.
- apply H2, ind_0_1_SS.
@@ -105,17 +105,17 @@ Hint Resolve double_S: arith.
Lemma even_odd_double n :
(even n <-> n = double (div2 n)) /\ (odd n <-> n = S (double (div2 n))).
Proof.
- revert n. fix even_odd_double 1. destruct n as [|[|n]].
+ revert n. fix even_odd_double 1. intros n; destruct n as [|[|n]].
- (* n = 0 *)
split; split; auto with arith. inversion 1.
- (* n = 1 *)
- split; split; auto with arith. inversion_clear 1. inversion H0.
+ split; split; auto with arith. inversion_clear 1 as [|? H0]. inversion H0.
- (* n = (S (S n')) *)
destruct (even_odd_double n) as ((Ev,Ev'),(Od,Od')).
split; split; simpl div2; rewrite ?double_S.
- + inversion_clear 1. inversion_clear H0. auto.
+ + inversion_clear 1 as [|? H0]. inversion_clear H0. auto.
+ injection 1. auto with arith.
- + inversion_clear 1. inversion_clear H0. auto.
+ + inversion_clear 1 as [? H0]. inversion_clear H0. auto.
+ injection 1. auto with arith.
Qed.
diff --git a/theories/Arith/Euclid.v b/theories/Arith/Euclid.v
index fdd149e01a..d5f715d843 100644
--- a/theories/Arith/Euclid.v
+++ b/theories/Arith/Euclid.v
@@ -21,7 +21,7 @@ Inductive diveucl a b : Set :=
Lemma eucl_dev : forall n, n > 0 -> forall m:nat, diveucl m n.
Proof.
- induction m as (m,H0) using gt_wf_rec.
+ intros n H m; induction m as (m,H0) using gt_wf_rec.
destruct (le_gt_dec n m) as [Hlebn|Hgtbn].
destruct (H0 (m - n)) as (q,r,Hge0,Heq); auto with arith.
apply divex with (S q) r; trivial.
@@ -34,7 +34,7 @@ Lemma quotient :
n > 0 ->
forall m:nat, {q : nat | exists r : nat, m = q * n + r /\ n > r}.
Proof.
- induction m as (m,H0) using gt_wf_rec.
+ intros n H m; induction m as (m,H0) using gt_wf_rec.
destruct (le_gt_dec n m) as [Hlebn|Hgtbn].
destruct (H0 (m - n)) as (q & Hq); auto with arith; exists (S q).
destruct Hq as (r & Heq & Hgt); exists r; split; trivial.
@@ -47,7 +47,7 @@ Lemma modulo :
n > 0 ->
forall m:nat, {r : nat | exists q : nat, m = q * n + r /\ n > r}.
Proof.
- induction m as (m,H0) using gt_wf_rec.
+ intros n H m; induction m as (m,H0) using gt_wf_rec.
destruct (le_gt_dec n m) as [Hlebn|Hgtbn].
destruct (H0 (m - n)) as (r & Hr); auto with arith; exists r.
destruct Hr as (q & Heq & Hgt); exists (S q); split; trivial.
diff --git a/theories/Arith/Even.v b/theories/Arith/Even.v
index 9c0a6bd96f..3422596818 100644
--- a/theories/Arith/Even.v
+++ b/theories/Arith/Even.v
@@ -39,28 +39,28 @@ Hint Constructors odd: arith.
Lemma even_equiv : forall n, even n <-> Nat.Even n.
Proof.
fix even_equiv 1.
- destruct n as [|[|n]]; simpl.
+ intros n; destruct n as [|[|n]]; simpl.
- split; [now exists 0 | constructor].
- split.
- + inversion_clear 1. inversion_clear H0.
+ + inversion_clear 1 as [|? H0]. inversion_clear H0.
+ now rewrite <- Nat.even_spec.
- rewrite Nat.Even_succ_succ, <- even_equiv.
split.
- + inversion_clear 1. now inversion_clear H0.
+ + inversion_clear 1 as [|? H0]. now inversion_clear H0.
+ now do 2 constructor.
Qed.
Lemma odd_equiv : forall n, odd n <-> Nat.Odd n.
Proof.
fix odd_equiv 1.
- destruct n as [|[|n]]; simpl.
+ intros n; destruct n as [|[|n]]; simpl.
- split.
+ inversion_clear 1.
+ now rewrite <- Nat.odd_spec.
- split; [ now exists 0 | do 2 constructor ].
- rewrite Nat.Odd_succ_succ, <- odd_equiv.
split.
- + inversion_clear 1. now inversion_clear H0.
+ + inversion_clear 1 as [? H0]. now inversion_clear H0.
+ now do 2 constructor.
Qed.
@@ -68,14 +68,14 @@ Qed.
Lemma even_or_odd n : even n \/ odd n.
Proof.
- induction n.
+ induction n as [|n IHn].
- auto with arith.
- elim IHn; auto with arith.
Qed.
Lemma even_odd_dec n : {even n} + {odd n}.
Proof.
- induction n.
+ induction n as [|n IHn].
- auto with arith.
- elim IHn; auto with arith.
Defined.
diff --git a/theories/Bool/Sumbool.v b/theories/Bool/Sumbool.v
index bea14480f8..52605a4667 100644
--- a/theories/Bool/Sumbool.v
+++ b/theories/Bool/Sumbool.v
@@ -16,7 +16,7 @@
(** A boolean is either [true] or [false], and this is decidable *)
Definition sumbool_of_bool : forall b:bool, {b = true} + {b = false}.
- destruct b; auto.
+ intros b; destruct b; auto.
Defined.
Hint Resolve sumbool_of_bool: bool.
@@ -24,13 +24,13 @@ Hint Resolve sumbool_of_bool: bool.
Definition bool_eq_rec :
forall (b:bool) (P:bool -> Set),
(b = true -> P true) -> (b = false -> P false) -> P b.
- destruct b; auto.
+ intros b; destruct b; auto.
Defined.
Definition bool_eq_ind :
forall (b:bool) (P:bool -> Prop),
(b = true -> P true) -> (b = false -> P false) -> P b.
- destruct b; auto.
+ intros b; destruct b; auto.
Defined.
diff --git a/theories/Classes/DecidableClass.v b/theories/Classes/DecidableClass.v
index 94fcd55aa5..7169aa673d 100644
--- a/theories/Classes/DecidableClass.v
+++ b/theories/Classes/DecidableClass.v
@@ -65,6 +65,16 @@ Tactic Notation "decide" constr(P) :=
Require Import Bool Arith ZArith.
+Program Instance Decidable_not {P} `{Decidable P} : Decidable (~ P) := {
+ Decidable_witness := negb Decidable_witness
+}.
+Next Obligation.
+ split; intro Heq.
+ - apply negb_true_iff in Heq.
+ eapply Decidable_complete_alt; intuition.
+ - erewrite Decidable_sound_alt; intuition.
+Qed.
+
Program Instance Decidable_eq_bool : forall (x y : bool), Decidable (eq x y) := {
Decidable_witness := Bool.eqb x y
}.
diff --git a/theories/Compat/Coq810.v b/theories/Compat/Coq810.v
deleted file mode 100644
index d559bd96c3..0000000000
--- a/theories/Compat/Coq810.v
+++ /dev/null
@@ -1,13 +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) *)
-(************************************************************************)
-
-(** Compatibility file for making Coq act similar to Coq v8.10 *)
-
-Require Export Coq.Compat.Coq811.
diff --git a/theories/Init/Byte.v b/theories/Init/Byte.v
index 7449b52d76..e03820ef22 100644
--- a/theories/Init/Byte.v
+++ b/theories/Init/Byte.v
@@ -16,7 +16,7 @@ Require Import Coq.Init.Logic.
Require Import Coq.Init.Specif.
Require Coq.Init.Nat.
-Declare ML Module "string_notation_plugin".
+Declare ML Module "number_string_notation_plugin".
(** We define an inductive for use with the [String Notation] command
which contains all ascii characters. We use 256 constructors for
diff --git a/theories/Init/Decimal.v b/theories/Init/Decimal.v
index 025264ab01..bb12f9ca3e 100644
--- a/theories/Init/Decimal.v
+++ b/theories/Init/Decimal.v
@@ -118,6 +118,12 @@ Definition opp (d:int) :=
| Neg d => Pos d
end.
+Definition abs (d:int) : uint :=
+ match d with
+ | Pos d => d
+ | Neg d => d
+ end.
+
(** For conversions with binary numbers, it is easier to operate
on little-endian numbers. *)
diff --git a/theories/Init/Hexadecimal.v b/theories/Init/Hexadecimal.v
index 36f5e5ad1f..7467aa1262 100644
--- a/theories/Init/Hexadecimal.v
+++ b/theories/Init/Hexadecimal.v
@@ -125,6 +125,12 @@ Definition opp (d:int) :=
| Neg d => Pos d
end.
+Definition abs (d:int) : uint :=
+ match d with
+ | Pos d => d
+ | Neg d => d
+ end.
+
(** For conversions with binary numbers, it is easier to operate
on little-endian numbers. *)
@@ -173,6 +179,38 @@ 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
+ | Da d | Db d | Dc d | Dd d | De d | Df d =>
+ del_head n d
+ end
+ end.
+
+Definition del_head_int n d :=
+ match d with
+ | Pos d => del_head n d
+ | Neg d => 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. *)
+
+Definition 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/Nat.v b/theories/Init/Nat.v
index 7c8cf0b536..9a3a3ec99b 100644
--- a/theories/Init/Nat.v
+++ b/theories/Init/Nat.v
@@ -9,7 +9,7 @@
(************************************************************************)
Require Import Notations Logic Datatypes.
-Require Decimal Hexadecimal Numeral.
+Require Decimal Hexadecimal Number.
Local Open Scope nat_scope.
(**********************************************************************)
@@ -212,10 +212,10 @@ Fixpoint of_hex_uint_acc (d:Hexadecimal.uint)(acc:nat) :=
Definition of_hex_uint (d:Hexadecimal.uint) := of_hex_uint_acc d O.
-Definition of_num_uint (d:Numeral.uint) :=
+Definition of_num_uint (d:Number.uint) :=
match d with
- | Numeral.UIntDec d => of_uint d
- | Numeral.UIntHex d => of_hex_uint d
+ | Number.UIntDecimal d => of_uint d
+ | Number.UIntHexadecimal d => of_hex_uint d
end.
Fixpoint to_little_uint n acc :=
@@ -236,9 +236,9 @@ Fixpoint to_little_hex_uint n acc :=
Definition to_hex_uint n :=
Hexadecimal.rev (to_little_hex_uint n Hexadecimal.zero).
-Definition to_num_uint n := Numeral.UIntDec (to_uint n).
+Definition to_num_uint n := Number.UIntDecimal (to_uint n).
-Definition to_num_hex_uint n := Numeral.UIntHex (to_hex_uint n).
+Definition to_num_hex_uint n := Number.UIntHexadecimal (to_hex_uint n).
Definition of_int (d:Decimal.int) : option nat :=
match Decimal.norm d with
@@ -252,17 +252,17 @@ Definition of_hex_int (d:Hexadecimal.int) : option nat :=
| _ => None
end.
-Definition of_num_int (d:Numeral.int) : option nat :=
+Definition of_num_int (d:Number.int) : option nat :=
match d with
- | Numeral.IntDec d => of_int d
- | Numeral.IntHex d => of_hex_int d
+ | Number.IntDecimal d => of_int d
+ | Number.IntHexadecimal d => of_hex_int d
end.
Definition to_int n := Decimal.Pos (to_uint n).
Definition to_hex_int n := Hexadecimal.Pos (to_hex_uint n).
-Definition to_num_int n := Numeral.IntDec (to_int n).
+Definition to_num_int n := Number.IntDecimal (to_int n).
(** ** Euclidean division *)
diff --git a/theories/Init/Number.v b/theories/Init/Number.v
new file mode 100644
index 0000000000..eb9cc856ac
--- /dev/null
+++ b/theories/Init/Number.v
@@ -0,0 +1,45 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(** * Decimal or Hexadecimal numbers *)
+
+Require Import Decimal Hexadecimal.
+
+Variant uint := UIntDecimal (u:Decimal.uint) | UIntHexadecimal (u:Hexadecimal.uint).
+#[deprecated(since="8.13",note="Use UintDecimal instead.")]
+Notation UIntDec := UIntDecimal (only parsing).
+#[deprecated(since="8.13",note="Use UintHexadecimal instead.")]
+Notation UIntHex := UIntHexadecimal (only parsing).
+
+Variant int := IntDecimal (i:Decimal.int) | IntHexadecimal (i:Hexadecimal.int).
+#[deprecated(since="8.13",note="Use IntDecimal instead.")]
+Notation IntDec := IntDecimal (only parsing).
+#[deprecated(since="8.13",note="Use IntHexadecimal instead.")]
+Notation IntHex := IntHexadecimal (only parsing).
+
+Variant number := Decimal (d:Decimal.decimal) | Hexadecimal (h:Hexadecimal.hexadecimal).
+#[deprecated(since="8.13",note="Use Decimal instead.")]
+Notation Dec := Decimal (only parsing).
+#[deprecated(since="8.13",note="Use Hexadecimal instead.")]
+Notation Hex := Hexadecimal (only parsing).
+
+Scheme Equality for uint.
+Scheme Equality for int.
+Scheme Equality for number.
+
+Register uint as num.num_uint.type.
+Register int as num.num_int.type.
+Register number as num.number.type.
+
+(** Pseudo-conversion functions used when declaring
+ Number Notations on [uint] and [int]. *)
+
+Definition uint_of_uint (i:uint) := i.
+Definition int_of_int (i:int) := i.
diff --git a/theories/Init/Numeral.v b/theories/Init/Numeral.v
index 179547d0b3..50fa312e7e 100644
--- a/theories/Init/Numeral.v
+++ b/theories/Init/Numeral.v
@@ -8,26 +8,47 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-(** * Decimal or Hexadecimal numbers *)
-
-Require Import Decimal Hexadecimal.
-
-Variant uint := UIntDec (u:Decimal.uint) | UIntHex (u:Hexadecimal.uint).
-
-Variant int := IntDec (i:Decimal.int) | IntHex (i:Hexadecimal.int).
-
-Variant numeral := Dec (d:Decimal.decimal) | Hex (h:Hexadecimal.hexadecimal).
-
-Scheme Equality for uint.
-Scheme Equality for int.
-Scheme Equality for numeral.
-
-Register uint as num.num_uint.type.
-Register int as num.num_int.type.
-Register numeral as num.numeral.type.
-
-(** Pseudo-conversion functions used when declaring
- Number Notations on [uint] and [int]. *)
-
-Definition uint_of_uint (i:uint) := i.
-Definition int_of_int (i:int) := i.
+(** * Deprecated: use Number.v instead *)
+
+Require Import Decimal Hexadecimal Number.
+
+#[deprecated(since="8.13",note="Use Number.uint instead.")]
+Notation uint := uint (only parsing).
+#[deprecated(since="8.13",note="Use Number.UintDecimal instead.")]
+Notation UIntDec := UIntDecimal (only parsing).
+#[deprecated(since="8.13",note="Use Number.UintHexadecimal instead.")]
+Notation UIntHex := UIntHexadecimal (only parsing).
+
+#[deprecated(since="8.13",note="Use Number.int instead.")]
+Notation int := int (only parsing).
+#[deprecated(since="8.13",note="Use Number.IntDecimal instead.")]
+Notation IntDec := IntDecimal (only parsing).
+#[deprecated(since="8.13",note="Use Number.IntHexadecimal instead.")]
+Notation IntHex := IntHexadecimal (only parsing).
+
+#[deprecated(since="8.13",note="Use Number.numeral instead.")]
+Notation numeral := number (only parsing).
+#[deprecated(since="8.13",note="Use Number.Decimal instead.")]
+Notation Dec := Decimal (only parsing).
+#[deprecated(since="8.13",note="Use Number.Hexadecimal instead.")]
+Notation Hex := Hexadecimal (only parsing).
+
+#[deprecated(since="8.13",note="Use Number.uint_beq instead.")]
+Notation uint_beq := uint_beq (only parsing).
+#[deprecated(since="8.13",note="Use Number.uint_eq_dec instead.")]
+Notation uint_eq_dec := uint_eq_dec (only parsing).
+#[deprecated(since="8.13",note="Use Number.int_beq instead.")]
+Notation int_beq := int_beq (only parsing).
+#[deprecated(since="8.13",note="Use Number.int_eq_dec instead.")]
+Notation int_eq_dec := int_eq_dec (only parsing).
+#[deprecated(since="8.13",note="Use Number.numeral_beq instead.")]
+Notation numeral_beq := number_beq (only parsing).
+#[deprecated(since="8.13",note="Use Number.numeral_eq_dec instead.")]
+Notation numeral_eq_dec := number_eq_dec (only parsing).
+
+Register number as num.numeral.type.
+
+#[deprecated(since="8.13",note="Use Number.uint_of_uint instead.")]
+Notation uint_of_uint := uint_of_uint (only parsing).
+#[deprecated(since="8.13",note="Use Number.int_of_int instead.")]
+Notation int_of_int := int_of_int (only parsing).
diff --git a/theories/Init/Prelude.v b/theories/Init/Prelude.v
index 0fe3d5491e..9f8a054b5c 100644
--- a/theories/Init/Prelude.v
+++ b/theories/Init/Prelude.v
@@ -17,6 +17,7 @@ Require Coq.Init.Byte.
Require Coq.Init.Decimal.
Require Coq.Init.Hexadecimal.
Require Coq.Init.Numeral.
+Require Coq.Init.Number.
Require Coq.Init.Nat.
Require Export Peano.
Require Export Coq.Init.Wf.
@@ -29,28 +30,26 @@ Require Export Coq.Init.Tauto.
*)
Declare ML Module "cc_plugin".
Declare ML Module "ground_plugin".
-Declare ML Module "numeral_notation_plugin".
-Declare ML Module "string_notation_plugin".
(* Parsing / printing of hexadecimal numbers *)
Arguments Nat.of_hex_uint d%hex_uint_scope.
Arguments Nat.of_hex_int d%hex_int_scope.
-Number Notation Numeral.uint Numeral.uint_of_uint Numeral.uint_of_uint
+Number Notation Number.uint Number.uint_of_uint Number.uint_of_uint
: hex_uint_scope.
-Number Notation Numeral.int Numeral.int_of_int Numeral.int_of_int
+Number Notation Number.int Number.int_of_int Number.int_of_int
: hex_int_scope.
(* Parsing / printing of decimal numbers *)
Arguments Nat.of_uint d%dec_uint_scope.
Arguments Nat.of_int d%dec_int_scope.
-Number Notation Numeral.uint Numeral.uint_of_uint Numeral.uint_of_uint
+Number Notation Number.uint Number.uint_of_uint Number.uint_of_uint
: dec_uint_scope.
-Number Notation Numeral.int Numeral.int_of_int Numeral.int_of_int
+Number Notation Number.int Number.int_of_int Number.int_of_int
: dec_int_scope.
(* Parsing / printing of [nat] numbers *)
-Number Notation nat Nat.of_num_uint Nat.to_num_hex_uint : hex_nat_scope (abstract after 5001).
-Number Notation nat Nat.of_num_uint Nat.to_num_uint : nat_scope (abstract after 5001).
+Number Notation nat Nat.of_num_uint Nat.to_num_hex_uint (abstract after 5001) : hex_nat_scope.
+Number Notation nat Nat.of_num_uint Nat.to_num_uint (abstract after 5001) : nat_scope.
(* Printing/Parsing of bytes *)
Export Byte.ByteSyntaxNotations.
diff --git a/theories/NArith/BinNatDef.v b/theories/NArith/BinNatDef.v
index 222e76c3e7..e57e5fe856 100644
--- a/theories/NArith/BinNatDef.v
+++ b/theories/NArith/BinNatDef.v
@@ -390,10 +390,10 @@ Definition of_uint (d:Decimal.uint) := Pos.of_uint d.
Definition of_hex_uint (d:Hexadecimal.uint) := Pos.of_hex_uint d.
-Definition of_num_uint (d:Numeral.uint) :=
+Definition of_num_uint (d:Number.uint) :=
match d with
- | Numeral.UIntDec d => of_uint d
- | Numeral.UIntHex d => of_hex_uint d
+ | Number.UIntDecimal d => of_uint d
+ | Number.UIntHexadecimal d => of_hex_uint d
end.
Definition of_int (d:Decimal.int) :=
@@ -408,10 +408,10 @@ Definition of_hex_int (d:Hexadecimal.int) :=
| Hexadecimal.Neg _ => None
end.
-Definition of_num_int (d:Numeral.int) :=
+Definition of_num_int (d:Number.int) :=
match d with
- | Numeral.IntDec d => of_int d
- | Numeral.IntHex d => of_hex_int d
+ | Number.IntDecimal d => of_int d
+ | Number.IntHexadecimal d => of_hex_int d
end.
Definition to_uint n :=
@@ -426,13 +426,13 @@ Definition to_hex_uint n :=
| pos p => Pos.to_hex_uint p
end.
-Definition to_num_uint n := Numeral.UIntDec (to_uint n).
+Definition to_num_uint n := Number.UIntDecimal (to_uint n).
Definition to_int n := Decimal.Pos (to_uint n).
Definition to_hex_int n := Hexadecimal.Pos (to_hex_uint n).
-Definition to_num_int n := Numeral.IntDec (to_int n).
+Definition to_num_int n := Number.IntDecimal (to_int n).
Number Notation N of_num_uint to_num_uint : N_scope.
diff --git a/theories/NArith/Ndigits.v b/theories/NArith/Ndigits.v
index 8280b7d01f..adeb527c1c 100644
--- a/theories/NArith/Ndigits.v
+++ b/theories/NArith/Ndigits.v
@@ -36,13 +36,13 @@ Notation Nxor_nilpotent := N.lxor_nilpotent (only parsing).
Lemma Ptestbit_Pbit :
forall p n, Pos.testbit p (N.of_nat n) = Pos.testbit_nat p n.
Proof.
- induction p as [p IH|p IH| ]; intros [|n]; simpl; trivial;
+ intro p; induction p as [p IH|p IH| ]; intros [|n]; simpl; trivial;
rewrite <- IH; f_equal; rewrite (pred_Sn n) at 2; now rewrite Nat2N.inj_pred.
Qed.
Lemma Ntestbit_Nbit : forall a n, N.testbit a (N.of_nat n) = N.testbit_nat a n.
Proof.
- destruct a. trivial. apply Ptestbit_Pbit.
+ intro a; destruct a. trivial. apply Ptestbit_Pbit.
Qed.
Lemma Pbit_Ptestbit :
@@ -54,7 +54,7 @@ Qed.
Lemma Nbit_Ntestbit :
forall a n, N.testbit_nat a (N.to_nat n) = N.testbit a n.
Proof.
- destruct a. trivial. apply Pbit_Ptestbit.
+ intro a; destruct a. trivial. apply Pbit_Ptestbit.
Qed.
(** Equivalence of shifts, index in [N] or [nat] *)
@@ -104,7 +104,7 @@ Qed.
Lemma Nshiftr_nat_spec : forall a n m,
N.testbit_nat (N.shiftr_nat a n) m = N.testbit_nat a (m+n).
Proof.
- induction n; intros m.
+ intros a n; induction n as [|n IHn]; intros m.
now rewrite <- plus_n_O.
simpl. rewrite <- plus_n_Sm, <- plus_Sn_m, <- IHn.
destruct (N.shiftr_nat a n) as [|[p|p|]]; simpl; trivial.
@@ -113,7 +113,7 @@ Qed.
Lemma Nshiftl_nat_spec_high : forall a n m, (n<=m)%nat ->
N.testbit_nat (N.shiftl_nat a n) m = N.testbit_nat a (m-n).
Proof.
- induction n; intros m H.
+ intros a n; induction n as [|n IHn]; intros m H.
- now rewrite Nat.sub_0_r.
- destruct m.
+ inversion H.
@@ -125,9 +125,9 @@ Qed.
Lemma Nshiftl_nat_spec_low : forall a n m, (m<n)%nat ->
N.testbit_nat (N.shiftl_nat a n) m = false.
Proof.
- induction n; intros m H. inversion H.
+ intros a n; induction n as [|n IHn]; intros m H. inversion H.
rewrite Nshiftl_nat_S.
- destruct m.
+ destruct m as [|m].
- destruct (N.shiftl_nat a n); trivial.
- apply Lt.lt_S_n in H.
specialize (IHn m H).
@@ -147,13 +147,13 @@ Lemma Pshiftl_nat_N :
forall p n, Npos (Pos.shiftl_nat p n) = N.shiftl_nat (Npos p) n.
Proof.
unfold Pos.shiftl_nat, N.shiftl_nat.
- induction n; simpl; auto. now rewrite <- IHn.
+ intros p n; induction n as [|n IHn]; simpl; auto. now rewrite <- IHn.
Qed.
Lemma Pshiftl_nat_plus : forall n m p,
Pos.shiftl_nat p (m + n) = Pos.shiftl_nat (Pos.shiftl_nat p n) m.
Proof.
- induction m; simpl; intros. reflexivity.
+ intros n m; induction m; simpl; intros. reflexivity.
now f_equal.
Qed.
@@ -221,13 +221,13 @@ Local Notation Step H := (fun n => H (S n)).
Lemma Pbit_faithful_0 : forall p, ~(Pos.testbit_nat p == (fun _ => false)).
Proof.
- induction p as [p IHp|p IHp| ]; intros H; try discriminate (H O).
+ intros p; induction p as [p IHp|p IHp| ]; intros H; try discriminate (H O).
apply (IHp (Step H)).
Qed.
Lemma Pbit_faithful : forall p p', Pos.testbit_nat p == Pos.testbit_nat p' -> p = p'.
Proof.
- induction p as [p IHp|p IHp| ]; intros [p'|p'|] H; trivial;
+ intros p; induction p as [p IHp|p IHp| ]; intros [p'|p'|] H; trivial;
try discriminate (H O).
f_equal. apply (IHp _ (Step H)).
destruct (Pbit_faithful_0 _ (Step H)).
@@ -260,25 +260,25 @@ Definition Neven (n:N) := N.odd n = false.
Lemma Nbit0_correct : forall n:N, N.testbit_nat n 0 = N.odd n.
Proof.
- destruct n; trivial.
+ intros n; destruct n as [|p]; trivial.
destruct p; trivial.
Qed.
Lemma Ndouble_bit0 : forall n:N, N.odd (N.double n) = false.
Proof.
- destruct n; trivial.
+ intros n; destruct n; trivial.
Qed.
Lemma Ndouble_plus_one_bit0 :
forall n:N, N.odd (N.succ_double n) = true.
Proof.
- destruct n; trivial.
+ intros n; destruct n; trivial.
Qed.
Lemma Ndiv2_double :
forall n:N, Neven n -> N.double (N.div2 n) = n.
Proof.
- destruct n. trivial. destruct p. intro H. discriminate H.
+ intros n; destruct n as [|p]. trivial. destruct p. intro H. discriminate H.
intros. reflexivity.
intro H. discriminate H.
Qed.
@@ -286,7 +286,7 @@ Qed.
Lemma Ndiv2_double_plus_one :
forall n:N, Nodd n -> N.succ_double (N.div2 n) = n.
Proof.
- destruct n. intro. discriminate H.
+ intros n; destruct n as [|p]. intro H. discriminate H.
destruct p. intros. reflexivity.
intro H. discriminate H.
intro. reflexivity.
@@ -295,21 +295,21 @@ Qed.
Lemma Ndiv2_correct :
forall (a:N) (n:nat), N.testbit_nat (N.div2 a) n = N.testbit_nat a (S n).
Proof.
- destruct a; trivial.
+ intros a; destruct a as [|p]; trivial.
destruct p; trivial.
Qed.
Lemma Nxor_bit0 :
forall a a':N, N.odd (N.lxor a a') = xorb (N.odd a) (N.odd a').
Proof.
- intros. rewrite <- Nbit0_correct, (Nxor_semantics a a' O).
+ intros a a'. rewrite <- Nbit0_correct, (Nxor_semantics a a' O).
rewrite Nbit0_correct, Nbit0_correct. reflexivity.
Qed.
Lemma Nxor_div2 :
forall a a':N, N.div2 (N.lxor a a') = N.lxor (N.div2 a) (N.div2 a').
Proof.
- intros. apply Nbit_faithful. unfold eqf. intro.
+ intros a a'. apply Nbit_faithful. unfold eqf. intro n.
rewrite (Nxor_semantics (N.div2 a) (N.div2 a') n), Ndiv2_correct, (Nxor_semantics a a' (S n)).
rewrite 2! Ndiv2_correct.
reflexivity.
@@ -319,7 +319,7 @@ Lemma Nneg_bit0 :
forall a a':N,
N.odd (N.lxor a a') = true -> N.odd a = negb (N.odd a').
Proof.
- intros.
+ intros a a' H.
rewrite <- true_xorb, <- H, Nxor_bit0, xorb_assoc,
xorb_nilpotent, xorb_false.
reflexivity.
@@ -328,21 +328,21 @@ Qed.
Lemma Nneg_bit0_1 :
forall a a':N, N.lxor a a' = Npos 1 -> N.odd a = negb (N.odd a').
Proof.
- intros. apply Nneg_bit0. rewrite H. reflexivity.
+ intros a a' H. apply Nneg_bit0. rewrite H. reflexivity.
Qed.
Lemma Nneg_bit0_2 :
forall (a a':N) (p:positive),
N.lxor a a' = Npos (xI p) -> N.odd a = negb (N.odd a').
Proof.
- intros. apply Nneg_bit0. rewrite H. reflexivity.
+ intros a a' p H. apply Nneg_bit0. rewrite H. reflexivity.
Qed.
Lemma Nsame_bit0 :
forall (a a':N) (p:positive),
N.lxor a a' = Npos (xO p) -> N.odd a = N.odd a'.
Proof.
- intros. rewrite <- (xorb_false (N.odd a)).
+ intros a a' p H. rewrite <- (xorb_false (N.odd a)).
assert (H0: N.odd (Npos (xO p)) = false) by reflexivity.
rewrite <- H0, <- H, Nxor_bit0, <- xorb_assoc, xorb_nilpotent, false_xorb.
reflexivity.
@@ -366,7 +366,7 @@ Lemma Nbit0_less :
forall a a',
N.odd a = false -> N.odd a' = true -> Nless a a' = true.
Proof.
- intros. destruct (N.discr (N.lxor a a')) as [(p,H2)|H1]. unfold Nless.
+ intros a a' H H0. destruct (N.discr (N.lxor a a')) as [(p,H2)|H1]. unfold Nless.
rewrite H2. destruct p. simpl. rewrite H, H0. reflexivity.
assert (H1: N.odd (N.lxor a a') = false) by (rewrite H2; reflexivity).
rewrite (Nxor_bit0 a a'), H, H0 in H1. discriminate H1.
@@ -379,7 +379,7 @@ Lemma Nbit0_gt :
forall a a',
N.odd a = true -> N.odd a' = false -> Nless a a' = false.
Proof.
- intros. destruct (N.discr (N.lxor a a')) as [(p,H2)|H1]. unfold Nless.
+ intros a a' H H0. destruct (N.discr (N.lxor a a')) as [(p,H2)|H1]. unfold Nless.
rewrite H2. destruct p. simpl. rewrite H, H0. reflexivity.
assert (H1: N.odd (N.lxor a a') = false) by (rewrite H2; reflexivity).
rewrite (Nxor_bit0 a a'), H, H0 in H1. discriminate H1.
@@ -390,13 +390,13 @@ Qed.
Lemma Nless_not_refl : forall a, Nless a a = false.
Proof.
- intro. unfold Nless. rewrite (N.lxor_nilpotent a). reflexivity.
+ intro a. unfold Nless. rewrite (N.lxor_nilpotent a). reflexivity.
Qed.
Lemma Nless_def_1 :
forall a a', Nless (N.double a) (N.double a') = Nless a a'.
Proof.
- destruct a; destruct a'. reflexivity.
+ intros a a'; destruct a as [|p]; destruct a' as [|p0]. reflexivity.
trivial.
unfold Nless. simpl. destruct p; trivial.
unfold Nless. simpl. destruct (Pos.lxor p p0). reflexivity.
@@ -407,7 +407,7 @@ Lemma Nless_def_2 :
forall a a',
Nless (N.succ_double a) (N.succ_double a') = Nless a a'.
Proof.
- destruct a; destruct a'. reflexivity.
+ intros a a'; destruct a as [|p]; destruct a' as [|p0]. reflexivity.
trivial.
unfold Nless. simpl. destruct p; trivial.
unfold Nless. simpl. destruct (Pos.lxor p p0). reflexivity.
@@ -430,20 +430,20 @@ Qed.
Lemma Nless_z : forall a, Nless a N0 = false.
Proof.
- induction a. reflexivity.
+ intros a; induction a as [|p]. reflexivity.
unfold Nless. rewrite (N.lxor_0_r (Npos p)). induction p; trivial.
Qed.
Lemma N0_less_1 :
forall a, Nless N0 a = true -> {p : positive | a = Npos p}.
Proof.
- destruct a. discriminate.
+ intros a; destruct a as [|p]. discriminate.
intros. exists p. reflexivity.
Qed.
Lemma N0_less_2 : forall a, Nless N0 a = false -> a = N0.
Proof.
- induction a as [|p]; intro H. trivial.
+ intros a; induction a as [|p]; intro H. trivial.
exfalso. induction p as [|p IHp|]; discriminate || simpl; auto using IHp.
Qed.
@@ -451,14 +451,14 @@ Lemma Nless_trans :
forall a a' a'',
Nless a a' = true -> Nless a' a'' = true -> Nless a a'' = true.
Proof.
- induction a as [|a IHa|a IHa] using N.binary_ind; intros a' a'' H H0.
+ intros a; induction a as [|a IHa|a IHa] using N.binary_ind; intros a' a'' H H0.
- case_eq (Nless N0 a'') ; intros Heqn.
+ trivial.
+ rewrite (N0_less_2 a'' Heqn), (Nless_z a') in H0. discriminate H0.
- induction a' as [|a' _|a' _] using N.binary_ind.
+ rewrite (Nless_z (N.double a)) in H. discriminate H.
+ rewrite (Nless_def_1 a a') in H.
- induction a'' using N.binary_ind.
+ induction a'' as [|a'' _|a'' _] using N.binary_ind.
* rewrite (Nless_z (N.double a')) in H0. discriminate H0.
* rewrite (Nless_def_1 a' a'') in H0. rewrite (Nless_def_1 a a'').
exact (IHa _ _ H H0).
@@ -470,7 +470,7 @@ Proof.
- induction a' as [|a' _|a' _] using N.binary_ind.
+ rewrite (Nless_z (N.succ_double a)) in H. discriminate H.
+ rewrite (Nless_def_4 a a') in H. discriminate H.
- + induction a'' using N.binary_ind.
+ + induction a'' as [|a'' _|a'' _] using N.binary_ind.
* rewrite (Nless_z (N.succ_double a')) in H0. discriminate H0.
* rewrite (Nless_def_4 a' a'') in H0. discriminate H0.
* rewrite (Nless_def_2 a' a'') in H0. rewrite (Nless_def_2 a a') in H.
@@ -480,7 +480,7 @@ Qed.
Lemma Nless_total :
forall a a', {Nless a a' = true} + {Nless a' a = true} + {a = a'}.
Proof.
- induction a using N.binary_rec; intro a'.
+ intro a; induction a as [|a IHa|a IHa] using N.binary_rec; intro a'.
- case_eq (Nless N0 a') ; intros Heqb.
+ left. left. auto.
+ right. rewrite (N0_less_2 a' Heqb). reflexivity.
@@ -553,9 +553,9 @@ Definition ByteV2N {n : nat} : ByteVector n -> N :=
Lemma Bv2N_N2Bv : forall n, Bv2N _ (N2Bv n) = n.
Proof.
-destruct n.
+intro n; destruct n as [|p].
simpl; auto.
-induction p; simpl in *; auto; rewrite IHp; simpl; auto.
+induction p as [p IHp|p IHp|]; simpl in *; auto; rewrite IHp; simpl; auto.
Qed.
(** The opposite composition is not so simple: if the considered
@@ -564,7 +564,7 @@ Qed.
Lemma Bv2N_Nsize : forall n (bv:Bvector n), N.size_nat (Bv2N n bv) <= n.
Proof.
-induction bv; intros.
+intros n bv; induction bv as [|h n bv]; intros.
auto.
simpl.
destruct h;
@@ -579,16 +579,16 @@ Lemma Bv2N_Nsize_1 : forall n (bv:Bvector (S n)),
Bsign _ bv = true <->
N.size_nat (Bv2N _ bv) = (S n).
Proof.
-apply Vector.rectS ; intros ; simpl.
+apply Vector.rectS ; intros a ; simpl.
destruct a ; compute ; split ; intros x ; now inversion x.
- destruct a, (Bv2N (S n) v) ;
+ intros n v IH; destruct a, (Bv2N (S n) v) ;
simpl ;intuition ; try discriminate.
Qed.
Lemma Bv2N_upper_bound (n : nat) (bv : Bvector n) :
(Bv2N bv < N.shiftl_nat 1 n)%N.
Proof with simpl; auto.
- induction bv...
+ induction bv as [|h]...
- constructor.
- destruct h.
+ apply N.succ_double_lt...
@@ -621,7 +621,7 @@ Fixpoint N2Bv_gen (n:nat)(a:N) : Bvector n :=
Lemma N2Bv_N2Bv_gen : forall (a:N), N2Bv a = N2Bv_gen (N.size_nat a) a.
Proof.
-destruct a; simpl.
+intro a; destruct a as [|p]; simpl.
auto.
induction p; simpl; intros; auto; congruence.
Qed.
@@ -632,7 +632,7 @@ Qed.
Lemma N2Bv_N2Bv_gen_above : forall (a:N)(k:nat),
N2Bv_gen (N.size_nat a + k) a = Vector.append (N2Bv a) (Bvect_false k).
Proof.
-destruct a; simpl.
+intros a k; destruct a as [|p]; simpl.
destruct k; simpl; auto.
induction p; simpl; intros;unfold Bcons; f_equal; auto.
Qed.
@@ -642,7 +642,7 @@ Qed.
Lemma N2Bv_Bv2N : forall n (bv:Bvector n),
N2Bv_gen n (Bv2N n bv) = bv.
Proof.
-induction bv; intros.
+intros n bv; induction bv as [|h n bv IHbv]; intros.
auto.
simpl.
generalize IHbv; clear IHbv.
@@ -658,7 +658,7 @@ Lemma Nbit0_Blow : forall n, forall (bv:Bvector (S n)),
N.odd (Bv2N _ bv) = Blow _ bv.
Proof.
apply Vector.caseS.
-intros.
+intros h n t.
unfold Blow.
simpl.
destruct (Bv2N n t); simpl;
@@ -670,9 +670,9 @@ Notation Bnth := (@Vector.nth_order bool).
Lemma Bnth_Nbit : forall n (bv:Bvector n) p (H:p<n),
Bnth bv H = N.testbit_nat (Bv2N _ bv) p.
Proof.
-induction bv; intros.
+intros n bv; induction bv as [|h n bv IHbv]; intros p H.
inversion H.
-destruct p ; simpl.
+destruct p as [|p]; simpl.
destruct (Bv2N n bv); destruct h; simpl in *; auto.
specialize IHbv with p (Lt.lt_S_n _ _ H).
simpl in * ; destruct (Bv2N n bv); destruct h; simpl in *; auto.
@@ -680,9 +680,9 @@ Qed.
Lemma Nbit_Nsize : forall n p, N.size_nat n <= p -> N.testbit_nat n p = false.
Proof.
-destruct n as [|n].
+intro n; destruct n as [|n].
simpl; auto.
-induction n; simpl in *; intros; destruct p; auto with arith.
+induction n; simpl in *; intros p H; destruct p; auto with arith.
inversion H.
inversion H.
Qed.
@@ -690,9 +690,9 @@ Qed.
Lemma Nbit_Bth: forall n p (H:p < N.size_nat n),
N.testbit_nat n p = Bnth (N2Bv n) H.
Proof.
-destruct n as [|n].
-inversion H.
-induction n ; destruct p ; unfold Vector.nth_order in *; simpl in * ; auto.
+intro n; destruct n as [|n].
+intros p H; inversion H.
+induction n ; intro p; destruct p ; unfold Vector.nth_order in *; simpl in * ; auto.
intros H ; destruct (Lt.lt_n_O _ (Lt.lt_S_n _ _ H)).
Qed.
@@ -701,8 +701,9 @@ Qed.
Lemma Nxor_BVxor : forall n (bv bv' : Bvector n),
Bv2N _ (BVxor _ bv bv') = N.lxor (Bv2N _ bv) (Bv2N _ bv').
Proof.
-apply Vector.rect2 ; intros.
+apply Vector.rect2.
now simpl.
+intros n v1 v2 H a b.
simpl.
destruct a, b, (Bv2N n v1), (Bv2N n v2); simpl in *; rewrite H ; now simpl.
Qed.
@@ -710,8 +711,8 @@ Qed.
Lemma Nand_BVand : forall n (bv bv' : Bvector n),
Bv2N _ (BVand _ bv bv') = N.land (Bv2N _ bv) (Bv2N _ bv').
Proof.
-refine (@Vector.rect2 _ _ _ _ _); simpl; intros; auto.
-rewrite H.
+refine (@Vector.rect2 _ _ _ _ _); simpl; auto.
+intros n v1 v2 H a b; rewrite H.
destruct a, b, (Bv2N n v1), (Bv2N n v2);
simpl; auto.
Qed.
@@ -719,15 +720,15 @@ Qed.
Lemma N2Bv_sized_Nsize (n : N) :
N2Bv_sized (N.size_nat n) n = N2Bv n.
Proof with simpl; auto.
- destruct n...
- induction p...
+ destruct n as [|p]...
+ induction p as [p IHp|p IHp|]...
all: rewrite IHp...
Qed.
Lemma N2Bv_sized_Bv2N (n : nat) (v : Bvector n) :
N2Bv_sized n (Bv2N n v) = v.
Proof with simpl; auto.
- induction v...
+ induction v as [|h n v IHv]...
destruct h;
unfold N2Bv_sized;
destruct (Bv2N n v) as [|[]];
@@ -737,6 +738,6 @@ Qed.
Lemma N2Bv_N2Bv_sized_above (a : N) (k : nat) :
N2Bv_sized (N.size_nat a + k) a = N2Bv a ++ Bvect_false k.
Proof with auto.
- destruct a...
+ destruct a as [|p]...
induction p; simpl; f_equal...
Qed.
diff --git a/theories/Numbers/AltBinNotations.v b/theories/Numbers/AltBinNotations.v
index 7c846571a7..c203c178f5 100644
--- a/theories/Numbers/AltBinNotations.v
+++ b/theories/Numbers/AltBinNotations.v
@@ -17,7 +17,7 @@
the [Decimal.int] representation. When working with numbers with
thousands of digits and more, conversion from/to [Decimal.int] can
become significantly slow. If that becomes a problem for your
- development, this file provides some alternative [Numeral
+ development, this file provides some alternative [Number
Notation] commands that use [Z] as bridge type. To enable these
commands, just be sure to [Require] this file after other files
defining numeral notations.
diff --git a/theories/Numbers/DecimalFacts.v b/theories/Numbers/DecimalFacts.v
index dd361562ba..87a9f704cd 100644
--- a/theories/Numbers/DecimalFacts.v
+++ b/theories/Numbers/DecimalFacts.v
@@ -10,175 +10,425 @@
(** * DecimalFacts : some facts about Decimal numbers *)
-Require Import Decimal Arith.
+Require Import Decimal Arith ZArith.
+
+Variant digits := d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 | d8 | d9.
+
+Fixpoint to_list (u : uint) : list digits :=
+ match u with
+ | Nil => nil
+ | D0 u => cons d0 (to_list u)
+ | D1 u => cons d1 (to_list u)
+ | D2 u => cons d2 (to_list u)
+ | D3 u => cons d3 (to_list u)
+ | D4 u => cons d4 (to_list u)
+ | D5 u => cons d5 (to_list u)
+ | D6 u => cons d6 (to_list u)
+ | D7 u => cons d7 (to_list u)
+ | D8 u => cons d8 (to_list u)
+ | D9 u => cons d9 (to_list u)
+ end.
-Lemma uint_dec (d d' : uint) : { d = d' } + { d <> d' }.
-Proof.
- decide equality.
-Defined.
+Fixpoint of_list (l : list digits) : uint :=
+ match l with
+ | nil => Nil
+ | cons d0 l => D0 (of_list l)
+ | cons d1 l => D1 (of_list l)
+ | cons d2 l => D2 (of_list l)
+ | cons d3 l => D3 (of_list l)
+ | cons d4 l => D4 (of_list l)
+ | cons d5 l => D5 (of_list l)
+ | cons d6 l => D6 (of_list l)
+ | cons d7 l => D7 (of_list l)
+ | cons d8 l => D8 (of_list l)
+ | cons d9 l => D9 (of_list l)
+ end.
-Lemma rev_revapp d d' :
- rev (revapp d d') = revapp d' d.
+Lemma of_list_to_list u : of_list (to_list u) = u.
+Proof. now induction u; [|simpl; rewrite IHu..]. Qed.
+
+Lemma to_list_of_list l : to_list (of_list l) = l.
+Proof. now induction l as [|h t IHl]; [|case h; simpl; rewrite IHl]. Qed.
+
+Lemma to_list_inj u u' : to_list u = to_list u' -> u = u'.
Proof.
- revert d'. induction d; simpl; intros; now rewrite ?IHd.
+ now intro H; rewrite <-(of_list_to_list u), <-(of_list_to_list u'), H.
Qed.
-Lemma rev_rev d : rev (rev d) = d.
+Lemma of_list_inj u u' : of_list u = of_list u' -> u = u'.
Proof.
- apply rev_revapp.
+ now intro H; rewrite <-(to_list_of_list u), <-(to_list_of_list u'), H.
Qed.
-Lemma revapp_rev_nil d : revapp (rev d) Nil = d.
-Proof. now fold (rev (rev d)); rewrite rev_rev. Qed.
+Lemma nb_digits_spec u : nb_digits u = length (to_list u).
+Proof. now induction u; [|simpl; rewrite IHu..]. Qed.
-Lemma app_nil_r d : app d Nil = d.
-Proof. now unfold app; rewrite revapp_rev_nil. Qed.
+Fixpoint lnzhead l :=
+ match l with
+ | nil => nil
+ | cons d l' =>
+ match d with
+ | d0 => lnzhead l'
+ | _ => l
+ end
+ end.
-Lemma app_int_nil_r d : app_int d Nil = d.
-Proof. now case d; intro d'; simpl; rewrite app_nil_r. Qed.
+Lemma nzhead_spec u : to_list (nzhead u) = lnzhead (to_list u).
+Proof. now induction u; [|simpl; rewrite IHu|..]. Qed.
+
+Definition lzero := cons d0 nil.
+
+Definition lunorm l :=
+ match lnzhead l with
+ | nil => lzero
+ | d => d
+ end.
+
+Lemma unorm_spec u : to_list (unorm u) = lunorm (to_list u).
+Proof. now unfold unorm, lunorm; rewrite <-nzhead_spec; case (nzhead u). Qed.
-Lemma revapp_revapp_1 d d' d'' :
- nb_digits d <= 1 ->
- revapp (revapp d d') d'' = revapp d' (revapp d d'').
+Lemma revapp_spec d d' :
+ to_list (revapp d d') = List.rev_append (to_list d) (to_list d').
+Proof. now revert d'; induction d; intro d'; [|simpl; rewrite IHd..]. Qed.
+
+Lemma rev_spec d : to_list (rev d) = List.rev (to_list d).
+Proof. now unfold rev; rewrite revapp_spec, List.rev_alt; simpl. Qed.
+
+Lemma app_spec d d' :
+ to_list (app d d') = Datatypes.app (to_list d) (to_list d').
Proof.
- now case d; clear d; intro d;
- [|case d; clear d; intro d;
- [|simpl; case nb_digits; [|intros n]; intros Hn; exfalso;
- [apply (Nat.nle_succ_diag_l _ Hn)|
- apply (Nat.nle_succ_0 _ (le_S_n _ _ Hn))]..]..].
+ unfold app.
+ now rewrite revapp_spec, List.rev_append_rev, rev_spec, List.rev_involutive.
Qed.
-Lemma nb_digits_pos d : d <> Nil -> 0 < nb_digits d.
-Proof. now case d; [|intros d' _; apply Nat.lt_0_succ..]. Qed.
+Definition lnztail l :=
+ let fix aux l_rev :=
+ match l_rev with
+ | cons d0 l_rev => let (r, n) := aux l_rev in pair r (S n)
+ | _ => pair l_rev O
+ end in
+ let (r, n) := aux (List.rev l) in pair (List.rev r) n.
-Lemma nb_digits_revapp d d' :
- nb_digits (revapp d d') = nb_digits d + nb_digits d'.
+Lemma nztail_spec d :
+ let (r, n) := nztail d in
+ let (r', n') := lnztail (to_list d) in
+ to_list r = r' /\ n = n'.
Proof.
- now revert d'; induction d; [|intro d'; simpl; rewrite IHd; simpl..].
+ unfold nztail, lnztail.
+ set (f := fix aux d_rev := match d_rev with
+ | D0 d_rev => let (r, n) := aux d_rev in (r, S n)
+ | _ => (d_rev, 0) end).
+ set (f' := fix aux (l_rev : list digits) : list digits * nat :=
+ match l_rev with
+ | cons d0 l_rev => let (r, n) := aux l_rev in (r, S n)
+ | _ => (l_rev, 0)
+ end).
+ rewrite <-(of_list_to_list (rev d)), rev_spec.
+ induction (List.rev _) as [|h t IHl]; [now simpl|].
+ case h; simpl; [|now rewrite rev_spec; simpl; rewrite to_list_of_list..].
+ now revert IHl; case f; intros r n; case f'; intros r' n' [-> ->].
Qed.
-Lemma nb_digits_rev u : nb_digits (rev u) = nb_digits u.
-Proof. now unfold rev; rewrite nb_digits_revapp. Qed.
+Lemma del_head_spec_0 d : del_head 0 d = d.
+Proof. now simpl. Qed.
-Lemma nb_digits_nzhead u : nb_digits (nzhead u) <= nb_digits u.
-Proof. now induction u; [|apply le_S|..]. Qed.
+Lemma del_head_spec_small n d :
+ n <= length (to_list d) -> to_list (del_head n d) = List.skipn n (to_list d).
+Proof.
+ revert d; induction n as [|n IHn]; intro d; [now simpl|].
+ now case d; [|intros d' H; apply IHn, le_S_n..].
+Qed.
-Lemma del_head_nb_digits (u:uint) : del_head (nb_digits u) u = Nil.
-Proof. now induction u. Qed.
+Lemma del_head_spec_large n d : length (to_list d) < n -> del_head n d = zero.
+Proof.
+ revert d; induction n; intro d; [now case d|].
+ now case d; [|intro d'; simpl; intro H; rewrite (IHn _ (lt_S_n _ _ H))..].
+Qed.
-Lemma nb_digits_del_head n u :
- n <= nb_digits u -> nb_digits (del_head n u) = nb_digits u - n.
+Lemma nb_digits_0 d : nb_digits d = 0 -> d = Nil.
Proof.
- revert u; induction n; intros u; [now rewrite Nat.sub_0_r|].
- now case u; clear u; intro u; [|intro Hn; apply IHn, le_S_n..].
+ rewrite nb_digits_spec, <-(of_list_to_list d).
+ now case (to_list d) as [|h t]; [|rewrite to_list_of_list].
Qed.
+Lemma nb_digits_n0 d : nb_digits d <> 0 -> d <> Nil.
+Proof. now case d; [|intros u _..]. Qed.
+
Lemma nb_digits_iter_D0 n d :
nb_digits (Nat.iter n D0 d) = n + nb_digits d.
Proof. now induction n; simpl; [|rewrite IHn]. Qed.
-Fixpoint nth n u :=
- match n with
- | O =>
- match u with
- | Nil => Nil
- | D0 d => D0 Nil
- | D1 d => D1 Nil
- | D2 d => D2 Nil
- | D3 d => D3 Nil
- | D4 d => D4 Nil
- | D5 d => D5 Nil
- | D6 d => D6 Nil
- | D7 d => D7 Nil
- | D8 d => D8 Nil
- | D9 d => D9 Nil
- end
- | S n =>
- match u with
- | Nil => Nil
- | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d =>
- nth n d
- end
- end.
+Lemma length_lnzhead l : length (lnzhead l) <= length l.
+Proof. now induction l as [|h t IHl]; [|case h; [apply le_S|..]]. Qed.
+
+Lemma nb_digits_nzhead u : nb_digits (nzhead u) <= nb_digits u.
+Proof. now induction u; [|apply le_S|..]. Qed.
+
+Lemma unorm_nzhead u : nzhead u <> Nil -> unorm u = nzhead u.
+Proof. now unfold unorm; case nzhead. Qed.
-Lemma nb_digits_nth n u : nb_digits (nth n u) <= 1.
+Lemma nb_digits_unorm u : u <> Nil -> nb_digits (unorm u) <= nb_digits u.
Proof.
- revert u; induction n.
- - now intro u; case u; [apply Nat.le_0_1|..].
- - intro u; case u; [apply Nat.le_0_1|intro u'; apply IHn..].
+ intro Hu; case (uint_eq_dec (nzhead u) Nil).
+ { unfold unorm; intros ->; simpl.
+ now revert Hu; case u; [|intros u' _; apply le_n_S, Nat.le_0_l..]. }
+ intro H; rewrite (unorm_nzhead _ H); apply nb_digits_nzhead.
Qed.
-Lemma del_head_nth n u :
- n < nb_digits u ->
- del_head n u = revapp (nth n u) (del_head (S n) u).
-Proof.
- revert u; induction n; intro u; [now case u|].
- now case u; [|intro u'; intro H; apply IHn, le_S_n..].
-Qed.
-
-Lemma nth_revapp_r n d d' :
- nb_digits d <= n ->
- nth n (revapp d d') = nth (n - nb_digits d) d'.
-Proof.
- revert d d'; induction n; intro d.
- - now case d; intro d';
- [case d'|intros d'' H; exfalso; revert H; apply Nat.nle_succ_0..].
- - now induction d;
- [intro d'; case d'|
- intros d' H;
- simpl revapp; rewrite IHd; [|now apply le_Sn_le];
- rewrite Nat.sub_succ_l; [|now apply le_S_n];
- simpl; rewrite <-(IHn _ _ (le_S_n _ _ H))..].
-Qed.
-
-Lemma nth_revapp_l n d d' :
- n < nb_digits d ->
- nth n (revapp d d') = nth (nb_digits d - n - 1) d.
-Proof.
- revert d d'; induction n; intro d.
- - rewrite Nat.sub_0_r.
- now induction d;
- [|intros d' _; simpl revapp;
- revert IHd; case d; clear d; [|intro d..]; intro IHd;
- [|rewrite IHd; [simpl nb_digits; rewrite (Nat.sub_succ_l _ (S _))|];
- [|apply le_n_S, Nat.le_0_l..]..]..].
- - now induction d;
- [|intros d' H;
- simpl revapp; simpl nb_digits;
- simpl in H; generalize (lt_S_n _ _ H); clear H; intro H;
- case (le_lt_eq_dec _ _ H); clear H; intro H;
- [rewrite (IHd _ H), Nat.sub_succ_l;
- [rewrite Nat.sub_succ_l; [|apply Nat.le_add_le_sub_r]|
- apply le_Sn_le]|
- rewrite nth_revapp_r; rewrite <-H;
- [rewrite Nat.sub_succ, Nat.sub_succ_l; [rewrite !Nat.sub_diag|]|]]..].
-Qed.
-
-Lemma app_del_tail_head (u:uint) n :
- n <= nb_digits u ->
- app (del_tail n u) (del_head (nb_digits u - n) u) = u.
-Proof.
- unfold app, del_tail; rewrite rev_rev.
- induction n.
- - intros _; rewrite Nat.sub_0_r, del_head_nb_digits; simpl.
- now rewrite revapp_rev_nil.
- - intro Hn.
- rewrite (del_head_nth (_ - _));
- [|now apply Nat.sub_lt; [|apply Nat.lt_0_succ]].
- rewrite Nat.sub_succ_r, <-Nat.sub_1_r.
- rewrite <-(nth_revapp_l _ _ Nil Hn); fold (rev u).
- rewrite <-revapp_revapp_1; [|now apply nb_digits_nth].
- rewrite <-(del_head_nth _ _); [|now rewrite nb_digits_rev].
- rewrite Nat.sub_1_r, Nat.succ_pred_pos; [|now apply Nat.lt_add_lt_sub_r].
- apply (IHn (le_Sn_le _ _ Hn)).
+Lemma nb_digits_rev d : nb_digits (rev d) = nb_digits d.
+Proof. now rewrite !nb_digits_spec, rev_spec, List.rev_length. Qed.
+
+Lemma nb_digits_del_head_sub d n :
+ n <= nb_digits d ->
+ nb_digits (del_head (nb_digits d - n) d) = n.
+Proof.
+ rewrite !nb_digits_spec; intro Hn.
+ rewrite del_head_spec_small; [|now apply Nat.le_sub_l].
+ rewrite List.skipn_length, <-(Nat2Z.id (_ - _)).
+ rewrite Nat2Z.inj_sub; [|now apply Nat.le_sub_l].
+ rewrite (Nat2Z.inj_sub _ _ Hn).
+ rewrite Z.sub_sub_distr, Z.sub_diag; apply Nat2Z.id.
+Qed.
+
+Lemma unorm_D0 u : unorm (D0 u) = unorm u.
+Proof. reflexivity. Qed.
+
+Lemma app_nil_l d : app Nil d = d.
+Proof. now simpl. Qed.
+
+Lemma app_nil_r d : app d Nil = d.
+Proof. now apply to_list_inj; rewrite app_spec, List.app_nil_r. Qed.
+
+Lemma abs_app_int d d' : abs (app_int d d') = app (abs d) d'.
+Proof. now case d. Qed.
+
+Lemma abs_norm d : abs (norm d) = unorm (abs d).
+Proof. now case d as [u|u]; [|simpl; unfold unorm; case nzhead]. Qed.
+
+Lemma iter_D0_nzhead d :
+ Nat.iter (nb_digits d - nb_digits (nzhead d)) D0 (nzhead d) = d.
+Proof.
+ induction d; [now simpl| |now rewrite Nat.sub_diag..].
+ simpl nzhead; simpl nb_digits.
+ rewrite (Nat.sub_succ_l _ _ (nb_digits_nzhead _)).
+ now rewrite <-IHd at 4.
+Qed.
+
+Lemma iter_D0_unorm d :
+ d <> Nil ->
+ Nat.iter (nb_digits d - nb_digits (unorm d)) D0 (unorm d) = d.
+Proof.
+ case (uint_eq_dec (nzhead d) Nil); intro Hn.
+ { unfold unorm; rewrite Hn; simpl; intro H.
+ revert H Hn; induction d; [now simpl|intros _|now intros _..].
+ case (uint_eq_dec d Nil); simpl; intros H Hn; [now rewrite H|].
+ rewrite Nat.sub_0_r, (le_plus_minus 1 (nb_digits d)).
+ { now simpl; rewrite IHd. }
+ revert H; case d; [now simpl|intros u _; apply le_n_S, Nat.le_0_l..]. }
+ intros _; rewrite (unorm_nzhead _ Hn); apply iter_D0_nzhead.
+Qed.
+
+Lemma nzhead_app_l d d' :
+ nb_digits d' < nb_digits (nzhead (app d d')) ->
+ nzhead (app d d') = app (nzhead d) d'.
+Proof.
+ intro Hl; apply to_list_inj; revert Hl.
+ rewrite !nb_digits_spec, app_spec, !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl].
+ { now simpl; intro H; exfalso; revert H; apply le_not_lt, length_lnzhead. }
+ rewrite <-List.app_comm_cons.
+ now case h; [simpl; intro Hl; apply IHl|..].
+Qed.
+
+Lemma nzhead_app_r d d' :
+ nb_digits (nzhead (app d d')) <= nb_digits d' ->
+ nzhead (app d d') = nzhead d'.
+Proof.
+ intro Hl; apply to_list_inj; revert Hl.
+ rewrite !nb_digits_spec, !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl]; [now simpl|].
+ rewrite <-List.app_comm_cons.
+ now case h; [| simpl; rewrite List.app_length; intro Hl; exfalso; revert Hl;
+ apply le_not_lt, le_plus_r..].
+Qed.
+
+Lemma nzhead_app_nil_r d d' : nzhead (app d d') = Nil -> nzhead d' = Nil.
+Proof.
+now intro H; generalize H; rewrite nzhead_app_r; [|rewrite H; apply Nat.le_0_l].
+Qed.
+
+Lemma nzhead_app_nil d d' :
+ nb_digits (nzhead (app d d')) <= nb_digits d' -> nzhead d = Nil.
+Proof.
+ intro H; apply to_list_inj; revert H.
+ rewrite !nb_digits_spec, !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl]; [now simpl|].
+ now case h; [now simpl|..];
+ simpl;intro H; exfalso; revert H; apply le_not_lt;
+ rewrite List.app_length; apply le_plus_r.
+Qed.
+
+Lemma nzhead_app_nil_l d d' : nzhead (app d d') = Nil -> nzhead d = Nil.
+Proof.
+ intro H; apply to_list_inj; generalize (f_equal to_list H); clear H.
+ rewrite !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl]; [now simpl|].
+ now rewrite <-List.app_comm_cons; case h.
+Qed.
+
+Lemma unorm_app_zero d d' :
+ nb_digits (unorm (app d d')) <= nb_digits d' -> unorm d = zero.
+Proof.
+ unfold unorm.
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { now intro Hn; rewrite Hn, (nzhead_app_nil_l _ _ Hn). }
+ intro H; fold (unorm (app d d')); rewrite (unorm_nzhead _ H); intro H'.
+ case (uint_eq_dec (nzhead d) Nil); [now intros->|].
+ intro H''; fold (unorm d); rewrite (unorm_nzhead _ H'').
+ exfalso; apply H''; revert H'; apply nzhead_app_nil.
+Qed.
+
+Lemma app_int_nil_r d : app_int d Nil = d.
+Proof.
+ now case d; intro d'; simpl;
+ rewrite <-(of_list_to_list (app _ _)), app_spec;
+ rewrite List.app_nil_r, of_list_to_list.
+Qed.
+
+Lemma unorm_app_l d d' :
+ nb_digits d' < nb_digits (unorm (app d d')) ->
+ unorm (app d d') = app (unorm d) d'.
+Proof.
+ case (uint_eq_dec d' Nil); [now intros->; rewrite !app_nil_r|intro Hd'].
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { unfold unorm; intros->; simpl; intro H; exfalso; revert H; apply le_not_lt.
+ now revert Hd'; case d'; [|intros d'' _; apply le_n_S, Peano.le_0_n..]. }
+ intro Ha; rewrite (unorm_nzhead _ Ha).
+ intro Hn; generalize Hn; rewrite (nzhead_app_l _ _ Hn).
+ rewrite !nb_digits_spec, app_spec, List.app_length.
+ case (uint_eq_dec (nzhead d) Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply Nat.lt_irrefl. }
+ now intro H; rewrite (unorm_nzhead _ H).
+Qed.
+
+Lemma unorm_app_r d d' :
+ nb_digits (unorm (app d d')) <= nb_digits d' ->
+ unorm (app d d') = unorm d'.
+Proof.
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { now unfold unorm; intro H; rewrite H, (nzhead_app_nil_r _ _ H). }
+ intro Ha; rewrite (unorm_nzhead _ Ha).
+ case (uint_eq_dec (nzhead d') Nil).
+ { now intros H H'; exfalso; apply Ha; rewrite nzhead_app_r. }
+ intro Hd'; rewrite (unorm_nzhead _ Hd'); apply nzhead_app_r.
+Qed.
+
+Lemma norm_app_int d d' :
+ nb_digits d' < nb_digits (unorm (app (abs d) d')) ->
+ norm (app_int d d') = app_int (norm d) d'.
+Proof.
+ case (uint_eq_dec d' Nil); [now intros->; rewrite !app_int_nil_r|intro Hd'].
+ case d as [d|d]; [now simpl; intro H; apply f_equal, unorm_app_l|].
+ simpl; unfold unorm.
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply le_not_lt.
+ now revert Hd'; case d'; [|intros d'' _; apply le_n_S, Peano.le_0_n..]. }
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ intro Ha.
+ replace m with (nzhead (app d d')).
+ 2:{ now unfold m; revert Ha; case nzhead. }
+ intro Hn; generalize Hn; rewrite (nzhead_app_l _ _ Hn).
+ case (uint_eq_dec (app (nzhead d) d') Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply le_not_lt, Nat.le_0_l. }
+ clear m; set (m := match app _ _ with Nil => _ | _ => _ end).
+ intro Ha'.
+ replace m with (Neg (app (nzhead d) d')); [|now unfold m; revert Ha'; case app].
+ case (uint_eq_dec (nzhead d) Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply Nat.lt_irrefl. }
+ clear m; set (m := match nzhead _ with Nil => _ | _ => _ end).
+ intro Hd.
+ now replace m with (Neg (nzhead d)); [|unfold m; revert Hd; case nzhead].
+Qed.
+
+Lemma del_head_nb_digits d : del_head (nb_digits d) d = Nil.
+Proof.
+ apply to_list_inj.
+ rewrite nb_digits_spec, del_head_spec_small; [|now simpl].
+ now rewrite List.skipn_all.
+Qed.
+
+Lemma del_tail_nb_digits d : del_tail (nb_digits d) d = Nil.
+Proof. now unfold del_tail; rewrite <-nb_digits_rev, del_head_nb_digits. Qed.
+
+Lemma del_head_app n d d' :
+ n <= nb_digits d -> del_head n (app d d') = app (del_head n d) d'.
+Proof.
+ rewrite nb_digits_spec; intro Hn.
+ apply to_list_inj.
+ rewrite del_head_spec_small.
+ 2:{ now rewrite app_spec, List.app_length; apply le_plus_trans. }
+ rewrite !app_spec, (del_head_spec_small _ _ Hn).
+ rewrite List.skipn_app.
+ now rewrite (proj2 (Nat.sub_0_le _ _) Hn).
+Qed.
+
+Lemma del_tail_app n d d' :
+ n <= nb_digits d' -> del_tail n (app d d') = app d (del_tail n d').
+Proof.
+ rewrite nb_digits_spec; intro Hn.
+ unfold del_tail.
+ rewrite <-(of_list_to_list (rev (app d d'))), rev_spec, app_spec.
+ rewrite List.rev_app_distr, <-!rev_spec, <-app_spec, of_list_to_list.
+ rewrite del_head_app; [|now rewrite nb_digits_spec, rev_spec, List.rev_length].
+ apply to_list_inj.
+ rewrite rev_spec, !app_spec, !rev_spec.
+ now rewrite List.rev_app_distr, List.rev_involutive.
+Qed.
+
+Lemma del_tail_app_int n d d' :
+ n <= nb_digits d' -> del_tail_int n (app_int d d') = app_int d (del_tail n d').
+Proof. now case d as [d|d]; simpl; intro H; rewrite del_tail_app. Qed.
+
+Lemma app_del_tail_head n (d:uint) :
+ n <= nb_digits d -> app (del_tail n d) (del_head (nb_digits d - n) d) = d.
+Proof.
+ rewrite nb_digits_spec; intro Hn; unfold del_tail.
+ rewrite <-(of_list_to_list (app _ _)), app_spec, rev_spec.
+ rewrite del_head_spec_small; [|now rewrite rev_spec, List.rev_length].
+ rewrite del_head_spec_small; [|now apply Nat.le_sub_l].
+ rewrite rev_spec.
+ set (n' := _ - n).
+ assert (Hn' : n = length (to_list d) - n').
+ { now apply plus_minus; rewrite Nat.add_comm; symmetry; apply le_plus_minus_r. }
+ now rewrite Hn', <-List.firstn_skipn_rev, List.firstn_skipn, of_list_to_list.
Qed.
Lemma app_int_del_tail_head n (d:int) :
- let ad := match d with Pos d | Neg d => d end in
- n <= nb_digits ad ->
- app_int (del_tail_int n d) (del_head (nb_digits ad - n) ad) = d.
+ n <= nb_digits (abs d) ->
+ app_int (del_tail_int n d) (del_head (nb_digits (abs d) - n) (abs d)) = d.
Proof. now case d; clear d; simpl; intros u Hu; rewrite app_del_tail_head. Qed.
+Lemma del_head_app_int_exact i f :
+ nb_digits f < nb_digits (unorm (app (abs i) f)) ->
+ del_head (nb_digits (unorm (app (abs i) f)) - nb_digits f) (unorm (app (abs i) f)) = f.
+Proof.
+ simpl; intro Hnb; generalize Hnb; rewrite (unorm_app_l _ _ Hnb); clear Hnb.
+ replace (_ - _) with (nb_digits (unorm (abs i))).
+ - now rewrite del_head_app; [rewrite del_head_nb_digits|].
+ - rewrite !nb_digits_spec, app_spec, List.app_length.
+ now rewrite Nat.add_comm, minus_plus.
+Qed.
+
+Lemma del_tail_app_int_exact i f :
+ nb_digits f < nb_digits (unorm (app (abs i) f)) ->
+ del_tail_int (nb_digits f) (norm (app_int i f)) = norm i.
+Proof.
+ simpl; intro Hnb.
+ rewrite (norm_app_int _ _ Hnb).
+ rewrite del_tail_app_int; [|now simpl].
+ now rewrite del_tail_nb_digits, app_int_nil_r.
+Qed.
+
(** Normalization on little-endian numbers *)
Fixpoint nztail d :=
@@ -224,10 +474,13 @@ Proof.
apply nzhead_revapp.
Qed.
+Lemma rev_rev d : rev (rev d) = d.
+Proof. now apply to_list_inj; rewrite !rev_spec, List.rev_involutive. Qed.
+
Lemma rev_nztail_rev d :
rev (nztail (rev d)) = nzhead d.
Proof.
- destruct (uint_dec (nztail (rev d)) Nil) as [H|H].
+ destruct (uint_eq_dec (nztail (rev d)) Nil) as [H|H].
- rewrite H. unfold rev; simpl.
rewrite <- (rev_rev d). symmetry.
now apply nzhead_revapp_0.
@@ -278,21 +531,9 @@ Proof.
unfold unorm. now destruct nzhead.
Qed.
-Lemma unorm_D0 u : unorm (D0 u) = unorm u.
-Proof. reflexivity. Qed.
-
Lemma unorm_iter_D0 n u : unorm (Nat.iter n D0 u) = unorm u.
Proof. now induction n. Qed.
-Lemma nb_digits_unorm u :
- u <> Nil -> nb_digits (unorm u) <= nb_digits u.
-Proof.
- case u; clear u; [now simpl|intro u..]; [|now simpl..].
- intros _; unfold unorm.
- case_eq (nzhead (D0 u)); [|now intros u' <-; apply nb_digits_nzhead..].
- intros _; apply le_n_S, Nat.le_0_l.
-Qed.
-
Lemma del_head_nonnil n u :
n < nb_digits u -> del_head n u <> Nil.
Proof.
@@ -311,73 +552,78 @@ Proof.
now apply del_head_nonnil.
Qed.
-Lemma nzhead_invol d : nzhead (nzhead d) = nzhead d.
+Lemma nzhead_involutive d : nzhead (nzhead d) = nzhead d.
Proof.
now induction d.
Qed.
+#[deprecated(since="8.13",note="Use nzhead_involutive instead.")]
+Notation nzhead_invol := nzhead_involutive (only parsing).
-Lemma nztail_invol d : nztail (nztail d) = nztail d.
+Lemma nztail_involutive d : nztail (nztail d) = nztail d.
Proof.
rewrite <-(rev_rev (nztail _)), <-(rev_rev (nztail d)), <-(rev_rev d).
- now rewrite !rev_nztail_rev, nzhead_invol.
+ now rewrite !rev_nztail_rev, nzhead_involutive.
Qed.
+#[deprecated(since="8.13",note="Use nztail_involutive instead.")]
+Notation nztail_invol := nztail_involutive (only parsing).
-Lemma unorm_invol d : unorm (unorm d) = unorm d.
+Lemma unorm_involutive d : unorm (unorm d) = unorm d.
Proof.
unfold unorm.
destruct (nzhead d) eqn:E; trivial.
destruct (nzhead_nonzero _ _ E).
Qed.
+#[deprecated(since="8.13",note="Use unorm_involutive instead.")]
+Notation unorm_invol := unorm_involutive (only parsing).
-Lemma norm_invol d : norm (norm d) = norm d.
+Lemma norm_involutive d : norm (norm d) = norm d.
Proof.
unfold norm.
destruct d.
- - f_equal. apply unorm_invol.
+ - f_equal. apply unorm_involutive.
- destruct (nzhead d) eqn:E; auto.
destruct (nzhead_nonzero _ _ E).
Qed.
+#[deprecated(since="8.13",note="Use norm_involutive instead.")]
+Notation norm_invol := norm_involutive (only parsing).
+
+Lemma lnzhead_neq_d0_head l l' : ~(lnzhead l = cons d0 l').
+Proof. now induction l as [|h t Il]; [|case h]. Qed.
+
+Lemma lnzhead_head_nd0 h t : h <> d0 -> lnzhead (cons h t) = cons h t.
+Proof. now case h. Qed.
Lemma nzhead_del_tail_nzhead_eq n u :
nzhead u = u ->
n < nb_digits u ->
nzhead (del_tail n u) = del_tail n u.
Proof.
+ rewrite nb_digits_spec, <-List.rev_length.
intros Hu Hn.
- assert (Hhd : forall u,
- nzhead u = u <-> match nth 0 u with D0 _ => False | _ => True end).
- { clear n u Hu Hn; intro u.
- case u; clear u; [|intro u..]; [now simpl| |now simpl..]; simpl.
- split; [|now simpl].
- apply nzhead_nonzero. }
- assert (Hhd' : nth 0 (del_tail n u) = nth 0 u).
- { rewrite <-(app_del_tail_head _ _ (le_Sn_le _ _ Hn)) at 2.
- unfold app.
- rewrite nth_revapp_l.
- - rewrite <-(nth_revapp_l _ _ Nil).
- + now fold (rev (rev (del_tail n u))); rewrite rev_rev.
- + unfold del_tail; rewrite rev_rev.
- rewrite nb_digits_del_head; rewrite nb_digits_rev.
- * now rewrite <-Nat.lt_add_lt_sub_r.
- * now apply Nat.lt_le_incl.
- - unfold del_tail; rewrite rev_rev.
- rewrite nb_digits_del_head; rewrite nb_digits_rev.
- + now rewrite <-Nat.lt_add_lt_sub_r.
- + now apply Nat.lt_le_incl. }
- revert Hu; rewrite Hhd; intro Hu.
- now rewrite Hhd, Hhd'.
+ apply to_list_inj; unfold del_tail.
+ rewrite nzhead_spec, rev_spec.
+ rewrite del_head_spec_small; [|now rewrite rev_spec; apply Nat.lt_le_incl].
+ rewrite rev_spec.
+ rewrite List.skipn_rev, List.rev_involutive.
+ generalize (f_equal to_list Hu) Hn; rewrite nzhead_spec; intro Hu'.
+ case (to_list u) as [|h t].
+ { simpl; intro H; exfalso; revert H; apply le_not_lt, Peano.le_0_n. }
+ intro Hn'; generalize (Nat.sub_gt _ _ Hn'); rewrite List.rev_length.
+ case (_ - _); [now simpl|]; intros n' _.
+ rewrite List.firstn_cons, lnzhead_head_nd0; [now simpl|].
+ intro Hh; revert Hu'; rewrite Hh; apply lnzhead_neq_d0_head.
Qed.
Lemma nzhead_del_tail_nzhead n u :
n < nb_digits (nzhead u) ->
nzhead (del_tail n (nzhead u)) = del_tail n (nzhead u).
-Proof. apply nzhead_del_tail_nzhead_eq, nzhead_invol. Qed.
+Proof. apply nzhead_del_tail_nzhead_eq, nzhead_involutive. Qed.
Lemma unorm_del_tail_unorm n u :
n < nb_digits (unorm u) ->
unorm (del_tail n (unorm u)) = del_tail n (unorm u).
Proof.
- case (uint_dec (nzhead u) Nil).
+ case (uint_eq_dec (nzhead u) Nil).
- unfold unorm; intros->; case n; [now simpl|]; intro n'.
now simpl; intro H; exfalso; generalize (lt_S_n _ _ H).
- unfold unorm.
@@ -396,7 +642,7 @@ Lemma norm_del_tail_int_norm n d :
Proof.
case d; clear d; intros u; simpl.
- now intro H; simpl; rewrite unorm_del_tail_unorm.
- - case (uint_dec (nzhead u) Nil); intro Hu.
+ - case (uint_eq_dec (nzhead u) Nil); intro Hu.
+ now rewrite Hu; case n; [|intros n' Hn'; generalize (lt_S_n _ _ Hn')].
+ set (m := match nzhead u with Nil => Pos zero | _ => _ end).
replace m with (Neg (nzhead u)); [|now unfold m; revert Hu; case nzhead].
@@ -418,7 +664,7 @@ Proof.
generalize (nzhead_revapp d d').
generalize (nzhead_revapp_0 (nztail d) d').
generalize (nzhead_revapp (nztail d) d').
- rewrite nztail_invol.
+ rewrite nztail_involutive.
now case nztail;
[intros _ H _ H'; rewrite (H eq_refl), (H' eq_refl)
|intros d'' H _ H' _; rewrite H; [rewrite H'|]..].
@@ -455,5 +701,10 @@ Proof.
|rewrite H'; unfold r; clear m r H'];
unfold norm;
rewrite rev_rev, <-Hd'';
- rewrite nzhead_revapp; rewrite nztail_invol; [|rewrite Hd'']..].
+ rewrite nzhead_revapp; rewrite nztail_involutive; [|rewrite Hd'']..].
+Qed.
+
+Lemma unorm_app_l_nil d d' : nzhead d = Nil -> unorm (app d d') = unorm d'.
+Proof.
+ now unfold unorm; rewrite <-nzhead_app_nzhead; intros->; rewrite app_nil_l.
Qed.
diff --git a/theories/Numbers/DecimalN.v b/theories/Numbers/DecimalN.v
index 8bc5c38fb5..a5dd97f24b 100644
--- a/theories/Numbers/DecimalN.v
+++ b/theories/Numbers/DecimalN.v
@@ -74,7 +74,7 @@ Proof.
destruct (norm d) eqn:Hd; intros [= <-].
unfold N.to_int. rewrite Unsigned.to_of. f_equal.
revert Hd; destruct d; simpl.
- - intros [= <-]. apply unorm_invol.
+ - intros [= <-]. apply unorm_involutive.
- destruct (nzhead d); now intros [= <-].
Qed.
@@ -93,7 +93,7 @@ Qed.
Lemma of_int_norm d : N.of_int (norm d) = N.of_int d.
Proof.
- unfold N.of_int. now rewrite norm_invol.
+ unfold N.of_int. now rewrite norm_involutive.
Qed.
Lemma of_inj_pos d d' :
diff --git a/theories/Numbers/DecimalNat.v b/theories/Numbers/DecimalNat.v
index 1962ac5d9d..4fee40caa2 100644
--- a/theories/Numbers/DecimalNat.v
+++ b/theories/Numbers/DecimalNat.v
@@ -270,7 +270,7 @@ Proof.
destruct (norm d) eqn:Hd; intros [= <-].
unfold Nat.to_int. rewrite Unsigned.to_of. f_equal.
revert Hd; destruct d; simpl.
- - intros [= <-]. apply unorm_invol.
+ - intros [= <-]. apply unorm_involutive.
- destruct (nzhead d); now intros [= <-].
Qed.
@@ -289,7 +289,7 @@ Qed.
Lemma of_int_norm d : Nat.of_int (norm d) = Nat.of_int d.
Proof.
- unfold Nat.of_int. now rewrite norm_invol.
+ unfold Nat.of_int. now rewrite norm_involutive.
Qed.
Lemma of_inj_pos d d' :
diff --git a/theories/Numbers/DecimalQ.v b/theories/Numbers/DecimalQ.v
index c51cced024..2027813eec 100644
--- a/theories/Numbers/DecimalQ.v
+++ b/theories/Numbers/DecimalQ.v
@@ -15,455 +15,413 @@
Require Import Decimal DecimalFacts DecimalPos DecimalN DecimalZ QArith.
-Lemma of_to (q:Q) : forall d, to_decimal q = Some d -> of_decimal d = q.
+Lemma of_IQmake_to_decimal num den :
+ match IQmake_to_decimal num den with
+ | None => True
+ | Some (DecimalExp _ _ _) => False
+ | Some (Decimal i f) => of_decimal (Decimal i f) = IQmake (IZ_of_Z num) den
+ end.
Proof.
- cut (match to_decimal q with None => True | Some d => of_decimal d = q end).
- { now case to_decimal; [intros d <- d' Hd'; injection Hd'; intros ->|]. }
- destruct q as (num, den).
- unfold to_decimal; simpl.
- generalize (DecimalPos.Unsigned.nztail_to_uint den).
- case Decimal.nztail; intros u n.
- case u; clear u; [intros; exact I|intros; exact I|intro u|intros; exact I..].
- case u; clear u; [|intros; exact I..].
- unfold Pos.of_uint, Pos.of_uint_acc; rewrite N.mul_1_l.
- case n.
- - unfold of_decimal, app_int, app, Z.to_int; simpl.
- intro H; inversion H as (H1); clear H H1.
- case num; [reflexivity|intro pnum; fold (rev (rev (Pos.to_uint pnum)))..].
- + rewrite rev_rev; simpl.
- now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
- + rewrite rev_rev; simpl.
- now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
- - clear n; intros n H.
- injection H; clear H; intros ->.
- case Nat.ltb.
- + unfold of_decimal.
- rewrite of_to.
- apply f_equal2; [|now simpl].
- unfold app_int, app, Z.to_int; simpl.
- now case num;
- [|intro pnum; fold (rev (rev (Pos.to_uint pnum)));
- rewrite rev_rev; unfold Z.of_int, Z.of_uint;
- rewrite DecimalPos.Unsigned.of_to..].
- + unfold of_decimal; case Nat.ltb_spec; intro Hn; simpl.
- * rewrite nb_digits_del_head; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply le_Sn_le].
- rewrite Z.sub_sub_distr, Z.sub_diag; simpl.
- rewrite <-(of_to num) at 4.
- now revert Hn; case Z.to_int; clear num; intros pnum Hn; simpl;
- (rewrite app_del_tail_head; [|now apply le_Sn_le]).
- * revert Hn.
- set (anum := match Z.to_int num with Pos i => i | _ => _ end).
- intro Hn.
- assert (H : exists l, nb_digits anum = S l).
- { exists (Nat.pred (nb_digits anum)); apply S_pred_pos.
- now unfold anum; case num;
- [apply Nat.lt_0_1|
- intro pnum; apply nb_digits_pos, Unsigned.to_uint_nonnil..]. }
- destruct H as (l, Hl); rewrite Hl.
- assert (H : forall n d, (nb_digits (Nat.iter n D0 d) = n + nb_digits d)%nat).
- { now intros n'; induction n'; intro d; [|simpl; rewrite IHn']. }
- rewrite H, Hl.
- rewrite Nat.add_succ_r, Nat.sub_add; [|now apply le_S_n; rewrite <-Hl].
- assert (H' : forall n d, Pos.of_uint (Nat.iter n D0 d) = Pos.of_uint d).
- { now intro n'; induction n'; intro d; [|simpl; rewrite IHn']. }
- now unfold anum; case num; simpl; [|intro pnum..];
- unfold app, Z.of_uint; simpl;
- rewrite H', ?DecimalPos.Unsigned.of_to.
+ unfold IQmake_to_decimal.
+ generalize (Unsigned.nztail_to_uint den).
+ case Decimal.nztail; intros den' e_den'.
+ case den'; [now simpl|now simpl| |now simpl..]; clear den'; intro den'.
+ case den'; [ |now simpl..]; clear den'.
+ case e_den' as [|e_den']; simpl; intro H; injection H; clear H; intros->.
+ { now unfold of_decimal; simpl; rewrite app_int_nil_r, DecimalZ.of_to. }
+ replace (10 ^ _)%positive with (Nat.iter (S e_den') (Pos.mul 10) 1%positive).
+ 2:{ induction e_den' as [|n IHn]; [now simpl| ].
+ now rewrite SuccNat2Pos.inj_succ, Pos.pow_succ_r, <-IHn. }
+ case Nat.ltb_spec; intro He_den'.
+ - unfold of_decimal; simpl.
+ rewrite app_int_del_tail_head; [|now apply Nat.lt_le_incl].
+ rewrite DecimalZ.of_to.
+ now rewrite nb_digits_del_head_sub; [|now apply Nat.lt_le_incl].
+ - unfold of_decimal; simpl.
+ rewrite nb_digits_iter_D0.
+ apply f_equal2.
+ + apply f_equal, DecimalZ.to_int_inj.
+ rewrite DecimalZ.to_of.
+ rewrite <-(DecimalZ.of_to num), DecimalZ.to_of.
+ case (Z.to_int num); clear He_den' num; intro num; simpl.
+ * unfold app; simpl.
+ now rewrite unorm_D0, unorm_iter_D0, unorm_involutive.
+ * case (uint_eq_dec (nzhead num) Nil); [|intro Hn].
+ { intros->; simpl; unfold app; simpl.
+ now rewrite unorm_D0, unorm_iter_D0. }
+ replace (match nzhead num with Nil => _ | _ => _ end)
+ with (Neg (nzhead num)); [|now revert Hn; case nzhead].
+ simpl.
+ rewrite nzhead_iter_D0, nzhead_involutive.
+ now revert Hn; case nzhead.
+ + revert He_den'; case nb_digits as [|n]; [now simpl; rewrite Nat.add_0_r|].
+ intro Hn.
+ rewrite Nat.add_succ_r, Nat.add_comm.
+ now rewrite <-le_plus_minus; [|apply le_S_n].
Qed.
-(* normalize without fractional part, for instance norme 12.3e-1 is 123e-2 *)
-Definition dnorme (d:decimal) : decimal :=
- let '(i, f, e) :=
- match d with
- | Decimal i f => (i, f, Pos Nil)
- | DecimalExp i f e => (i, f, e)
- end in
- let i := norm (app_int i f) in
- let e := norm (Z.to_int (Z.of_int e - Z.of_nat (nb_digits f))) in
- match e with
- | Pos zero => Decimal i Nil
- | _ => DecimalExp i Nil e
+Lemma IZ_of_Z_IZ_to_Z z z' : IZ_to_Z z = Some z' -> IZ_of_Z z' = z.
+Proof. now case z as [| |p|p]; [|intro H; injection H; intros<-..]. Qed.
+
+Lemma of_IQmake_to_decimal' num den :
+ match IQmake_to_decimal' num den with
+ | None => True
+ | Some (DecimalExp _ _ _) => False
+ | Some (Decimal i f) => of_decimal (Decimal i f) = IQmake num den
end.
+Proof.
+ unfold IQmake_to_decimal'.
+ case_eq (IZ_to_Z num); [intros num' Hnum'|now simpl].
+ generalize (of_IQmake_to_decimal num' den).
+ case IQmake_to_decimal as [d|]; [|now simpl].
+ case d as [i f|]; [|now simpl].
+ now rewrite (IZ_of_Z_IZ_to_Z _ _ Hnum').
+Qed.
+
+Lemma of_to (q:IQ) : forall d, to_decimal q = Some d -> of_decimal d = q.
+Proof.
+ intro d.
+ case q as [num den|q q'|q q']; simpl.
+ - generalize (of_IQmake_to_decimal' num den).
+ case IQmake_to_decimal' as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ now intros H H'; injection H'; clear H'; intros <-.
+ - case q as [num den| |]; [|now simpl..].
+ case q' as [num' den'| |]; [|now simpl..].
+ case num' as [z p| | |]; [|now simpl..].
+ case (Z.eq_dec z 10); [intros->|].
+ 2:{ case z; [now simpl| |now simpl]; intro pz'.
+ case pz'; [intros d0..| ]; [now simpl| |now simpl].
+ case d0; [intros d1..| ]; [ |now simpl..].
+ case d1; [intros d2..| ]; [now simpl| |now simpl].
+ now case d2. }
+ case (Pos.eq_dec den' 1%positive); [intros->|now case den'].
+ generalize (of_IQmake_to_decimal' num den).
+ case IQmake_to_decimal' as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros <-; clear num den.
+ intros H; injection H; clear H; intros<-.
+ unfold of_decimal; simpl.
+ now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+ - case q as [num den| |]; [|now simpl..].
+ case q' as [num' den'| |]; [|now simpl..].
+ case num' as [z p| | |]; [|now simpl..].
+ case (Z.eq_dec z 10); [intros->|].
+ 2:{ case z; [now simpl| |now simpl]; intro pz'.
+ case pz'; [intros d0..| ]; [now simpl| |now simpl].
+ case d0; [intros d1..| ]; [ |now simpl..].
+ case d1; [intros d2..| ]; [now simpl| |now simpl].
+ now case d2. }
+ case (Pos.eq_dec den' 1%positive); [intros->|now case den'].
+ generalize (of_IQmake_to_decimal' num den).
+ case IQmake_to_decimal' as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros <-; clear num den.
+ intros H; injection H; clear H; intros<-.
+ unfold of_decimal; simpl.
+ now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+Qed.
-(* normalize without exponent part, for instance norme 12.3e-1 is 1.23 *)
-Definition dnormf (d:decimal) : decimal :=
- match dnorme d with
- | Decimal i _ => Decimal i Nil
- | DecimalExp i _ e =>
- match Z.of_int e with
- | Z0 => Decimal i Nil
- | Zpos e => Decimal (norm (app_int i (Pos.iter D0 Nil e))) Nil
- | Zneg e =>
- let ne := Pos.to_nat e in
- let ai := match i with Pos d | Neg d => d end in
- let ni := nb_digits ai in
- if ne <? ni then
- Decimal (del_tail_int ne i) (del_head (ni - ne) ai)
- else
- let z := match i with Pos _ => Pos zero | Neg _ => Neg zero end in
- Decimal z (Nat.iter (ne - ni) D0 ai)
+Definition dnorm (d:decimal) : decimal :=
+ let norm_i i f :=
+ match i with
+ | Pos i => Pos (unorm i)
+ | Neg i => match nzhead (app i f) with Nil => Pos zero | _ => Neg (unorm i) end
+ end in
+ match d with
+ | Decimal i f => Decimal (norm_i i f) f
+ | DecimalExp i f e =>
+ match norm e with
+ | Pos zero => Decimal (norm_i i f) f
+ | e => DecimalExp (norm_i i f) f e
end
end.
-Lemma dnorme_spec d :
- match dnorme d with
- | Decimal i Nil => i = norm i
- | DecimalExp i Nil e => i = norm i /\ e = norm e /\ e <> Pos zero
- | _ => False
+Lemma dnorm_spec_i d :
+ let (i, f) :=
+ match d with Decimal i f => (i, f) | DecimalExp i f _ => (i, f) end in
+ let i' := match dnorm d with Decimal i _ => i | DecimalExp i _ _ => i end in
+ match i with
+ | Pos i => i' = Pos (unorm i)
+ | Neg i =>
+ (i' = Neg (unorm i) /\ (nzhead i <> Nil \/ nzhead f <> Nil))
+ \/ (i' = Pos zero /\ (nzhead i = Nil /\ nzhead f = Nil))
end.
Proof.
- case d; clear d; intros i f; [|intro e]; unfold dnorme; simpl.
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); [intros->|intro Hne'].
- + now rewrite norm_invol.
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- replace m with r; [now unfold r; rewrite !norm_invol|].
- unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..].
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); [intros->|intro Hne'].
- + now rewrite norm_invol.
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- replace m with r; [now unfold r; rewrite !norm_invol|].
- unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..].
+ case d as [i f|i f e]; case i as [i|i].
+ - now simpl.
+ - simpl; case (uint_eq_dec (nzhead (app i f)) Nil); intro Ha.
+ + rewrite Ha; right; split; [now simpl|split].
+ * now unfold unorm; rewrite (nzhead_app_nil_l _ _ Ha).
+ * now unfold unorm; rewrite (nzhead_app_nil_r _ _ Ha).
+ + left; split; [now revert Ha; case nzhead|].
+ case (uint_eq_dec (nzhead i) Nil).
+ * intro Hi; right; intro Hf; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ * now intro H; left.
+ - simpl; case (norm e); clear e; intro e; [|now simpl].
+ now case e; clear e; [|intro e..]; [|case e|..].
+ - simpl.
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ set (m' := match _ with Decimal _ _ => _ | _ => _ end).
+ replace m' with m.
+ 2:{ unfold m'; case (norm e); clear m' e; intro e; [|now simpl].
+ now case e; clear e; [|intro e..]; [|case e|..]. }
+ unfold m; case (uint_eq_dec (nzhead (app i f)) Nil); intro Ha.
+ + rewrite Ha; right; split; [now simpl|split].
+ * now unfold unorm; rewrite (nzhead_app_nil_l _ _ Ha).
+ * now unfold unorm; rewrite (nzhead_app_nil_r _ _ Ha).
+ + left; split; [now revert Ha; case nzhead|].
+ case (uint_eq_dec (nzhead i) Nil).
+ * intro Hi; right; intro Hf; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ * now intro H; left.
+Qed.
+
+Lemma dnorm_spec_f d :
+ let f := match d with Decimal _ f => f | DecimalExp _ f _ => f end in
+ let f' := match dnorm d with Decimal _ f => f | DecimalExp _ f _ => f end in
+ f' = f.
+Proof.
+ case d as [i f|i f e]; [now simpl|].
+ simpl; case (int_eq_dec (norm e) (Pos zero)); [now intros->|intro He].
+ set (i' := match i with Pos _ => _ | _ => _ end).
+ set (m := match norm e with Pos Nil => _ | _ => _ end).
+ replace m with (DecimalExp i' f (norm e)); [now simpl|].
+ unfold m; revert He; case (norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..].
Qed.
-Lemma dnormf_spec d :
- match dnormf d with
- | Decimal i f => i = Neg zero \/ i = norm i
- | _ => False
+Lemma dnorm_spec_e d :
+ match d, dnorm d with
+ | Decimal _ _, Decimal _ _ => True
+ | DecimalExp _ _ e, Decimal _ _ => norm e = Pos zero
+ | DecimalExp _ _ e, DecimalExp _ _ e' => e' = norm e /\ e' <> Pos zero
+ | Decimal _ _, DecimalExp _ _ _ => False
end.
Proof.
- case d; clear d; intros i f; [|intro e]; unfold dnormf, dnorme; simpl.
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); [intros->|intro Hne'].
- + now right; rewrite norm_invol.
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..]. }
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- case_eq (Z.of_int e'); [|intros pe'..]; intro Hpe';
- [now right; rewrite norm_invol..|].
- case Nat.ltb_spec.
- * now intro H; rewrite (norm_del_tail_int_norm _ _ H); right.
- * now intros _; case norm; intros _; [right|left].
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); [intros->|intro Hne'].
- + now right; rewrite norm_invol.
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..]. }
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- case_eq (Z.of_int e'); [|intros pe'..]; intro Hpe';
- [now right; rewrite norm_invol..|].
- case Nat.ltb_spec.
- * now intro H; rewrite (norm_del_tail_int_norm _ _ H); right.
- * now intros _; case norm; intros _; [right|left].
+ case d as [i f|i f e]; [now simpl|].
+ simpl; case (int_eq_dec (norm e) (Pos zero)); [now intros->|intro He].
+ set (i' := match i with Pos _ => _ | _ => _ end).
+ set (m := match norm e with Pos Nil => _ | _ => _ end).
+ replace m with (DecimalExp i' f (norm e)); [now simpl|].
+ unfold m; revert He; case (norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..].
Qed.
-Lemma dnorme_invol d : dnorme (dnorme d) = dnorme d.
+Lemma dnorm_involutive d : dnorm (dnorm d) = dnorm d.
Proof.
- case d; clear d; intros i f; [|intro e]; unfold dnorme; simpl.
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); intro Hne'.
- + rewrite Hne'; simpl; rewrite app_int_nil_r, norm_invol.
- revert Hne'.
- rewrite <-to_of.
- change (Pos zero) with (Z.to_int 0).
- intro H; generalize (to_int_inj _ _ H); clear H.
- unfold e'; rewrite DecimalZ.of_to.
- now case f; [rewrite app_int_nil_r|..].
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..]. }
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- unfold nb_digits, Z.of_nat; rewrite Z.sub_0_r, to_of, norm_invol.
- rewrite app_int_nil_r, norm_invol.
- set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..].
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); intro Hne'.
- + rewrite Hne'; simpl; rewrite app_int_nil_r, norm_invol.
- revert Hne'.
- rewrite <-to_of.
- change (Pos zero) with (Z.to_int 0).
- intro H; generalize (to_int_inj _ _ H); clear H.
- unfold e'; rewrite DecimalZ.of_to.
- now case f; [rewrite app_int_nil_r|..].
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..]. }
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- unfold nb_digits, Z.of_nat; rewrite Z.sub_0_r, to_of, norm_invol.
- rewrite app_int_nil_r, norm_invol.
- set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..].
+ case d as [i f|i f e]; case i as [i|i].
+ - now simpl; rewrite unorm_involutive.
+ - simpl; case (uint_eq_dec (nzhead (app i f)) Nil); [now intros->|intro Ha].
+ set (m := match nzhead _ with Nil =>_ | _ => _ end).
+ replace m with (Neg (unorm i)).
+ 2:{ now unfold m; revert Ha; case nzhead. }
+ case (uint_eq_dec (nzhead i) Nil); intro Hi.
+ + unfold unorm; rewrite Hi; simpl.
+ case (uint_eq_dec (nzhead f) Nil).
+ * intro Hf; exfalso; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ * now case nzhead.
+ + rewrite unorm_involutive, (unorm_nzhead _ Hi), nzhead_app_nzhead.
+ now revert Ha; case nzhead.
+ - simpl; case (int_eq_dec (norm e) (Pos zero)); intro He.
+ + now rewrite He; simpl; rewrite unorm_involutive.
+ + set (m := match norm e with Pos Nil => _ | _ => _ end).
+ replace m with (DecimalExp (Pos (unorm i)) f (norm e)).
+ 2:{ unfold m; revert He; case (norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..]. }
+ simpl; rewrite norm_involutive, unorm_involutive.
+ revert He; case (norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..].
+ - simpl; case (int_eq_dec (norm e) (Pos zero)); intro He.
+ + rewrite He; simpl.
+ case (uint_eq_dec (nzhead (app i f)) Nil); [now intros->|intro Ha].
+ set (m := match nzhead _ with Nil =>_ | _ => _ end).
+ replace m with (Neg (unorm i)).
+ 2:{ now unfold m; revert Ha; case nzhead. }
+ case (uint_eq_dec (nzhead i) Nil); intro Hi.
+ * unfold unorm; rewrite Hi; simpl.
+ case (uint_eq_dec (nzhead f) Nil).
+ -- intro Hf; exfalso; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ -- now case nzhead.
+ * rewrite unorm_involutive, (unorm_nzhead _ Hi), nzhead_app_nzhead.
+ now revert Ha; case nzhead.
+ + set (m := match norm e with Pos Nil => _ | _ => _ end).
+ pose (i' := match nzhead (app i f) with Nil => Pos zero | _ => Neg (unorm i) end).
+ replace m with (DecimalExp i' f (norm e)).
+ 2:{ unfold m; revert He; case (norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..]. }
+ simpl; rewrite norm_involutive.
+ set (i'' := match i' with Pos _ => _ | _ => _ end).
+ clear m; set (m := match norm e with Pos Nil => _ | _ => _ end).
+ replace m with (DecimalExp i'' f (norm e)).
+ 2:{ unfold m; revert He; case (norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..]. }
+ unfold i'', i'.
+ case (uint_eq_dec (nzhead (app i f)) Nil); [now intros->|intro Ha].
+ fold i'; replace i' with (Neg (unorm i)).
+ 2:{ now unfold i'; revert Ha; case nzhead. }
+ case (uint_eq_dec (nzhead i) Nil); intro Hi.
+ * unfold unorm; rewrite Hi; simpl.
+ case (uint_eq_dec (nzhead f) Nil).
+ -- intro Hf; exfalso; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ -- now case nzhead.
+ * rewrite unorm_involutive, (unorm_nzhead _ Hi), nzhead_app_nzhead.
+ now revert Ha; case nzhead.
Qed.
-Lemma dnormf_invol d : dnormf (dnormf d) = dnormf d.
+Lemma IZ_to_Z_IZ_of_Z z : IZ_to_Z (IZ_of_Z z) = Some z.
+Proof. now case z. Qed.
+
+Lemma dnorm_i_exact i f :
+ (nb_digits f < nb_digits (unorm (app (abs i) f)))%nat ->
+ match i with
+ | Pos i => Pos (unorm i)
+ | Neg i =>
+ match nzhead (app i f) with
+ | Nil => Pos zero
+ | _ => Neg (unorm i)
+ end
+ end = norm i.
Proof.
- case d; clear d; intros i f; [|intro e]; unfold dnormf, dnorme; simpl.
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); intro Hne'.
- + rewrite Hne'; simpl; rewrite app_int_nil_r, norm_invol.
- revert Hne'.
- rewrite <-to_of.
- change (Pos zero) with (Z.to_int 0).
- intro H; generalize (to_int_inj _ _ H); clear H.
- unfold e'; rewrite DecimalZ.of_to.
- now case f; [rewrite app_int_nil_r|..].
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..]. }
- rewrite of_int_norm.
- case_eq (Z.of_int e'); [|intro pe'..]; intro Hnpe';
- [now simpl; rewrite app_int_nil_r, norm_invol..|].
- case Nat.ltb_spec; intro Hpe'.
- * rewrite nb_digits_del_head; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply Nat.lt_le_incl].
- simpl.
- rewrite Z.sub_sub_distr, Z.sub_diag, Z.add_0_l.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- rewrite positive_nat_Z; simpl.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- rewrite app_int_del_tail_head; [|now apply Nat.lt_le_incl].
- now rewrite norm_invol, (proj2 (Nat.ltb_lt _ _) Hpe').
- * simpl.
- rewrite nb_digits_iter_D0.
- rewrite (Nat.sub_add _ _ Hpe').
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- rewrite positive_nat_Z; simpl.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- revert Hpe'.
- set (i' := norm (app_int i f)).
- case_eq i'; intros u Hu Hpe'.
- ++ simpl; unfold app; simpl.
- rewrite unorm_D0, unorm_iter_D0.
- assert (Hu' : unorm u = u).
- { generalize (f_equal norm Hu).
- unfold i'; rewrite norm_invol; fold i'.
- now simpl; rewrite Hu; intro H; injection H. }
- now rewrite Hu', (proj2 (Nat.ltb_ge _ _) Hpe').
- ++ simpl; rewrite nzhead_iter_D0.
- assert (Hu' : nzhead u = u).
- { generalize (f_equal norm Hu).
- unfold i'; rewrite norm_invol; fold i'.
- now rewrite Hu; simpl; case (nzhead u); [|intros u' H; injection H..]. }
- rewrite Hu'.
- assert (Hu'' : u <> Nil).
- { intro H; revert Hu; rewrite H; unfold i'.
- now case app_int; intro u'; [|simpl; case nzhead]. }
- set (m := match u with Nil => Pos zero | _ => _ end).
- assert (H : m = Neg u); [|rewrite H; clear m H].
- { now revert Hu''; unfold m; case u. }
- now rewrite (proj2 (Nat.ltb_ge _ _) Hpe').
- - set (e' := Z.to_int _).
- case (int_eq_dec (norm e') (Pos zero)); intro Hne'.
- + rewrite Hne'; simpl; rewrite app_int_nil_r, norm_invol.
- revert Hne'.
- rewrite <-to_of.
- change (Pos zero) with (Z.to_int 0).
- intro H; generalize (to_int_inj _ _ H); clear H.
- unfold e'; rewrite DecimalZ.of_to.
- now case f; [rewrite app_int_nil_r|..].
- + set (r := DecimalExp _ _ _).
- set (m := match norm e' with Pos zero => _ | _ => _ end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { unfold m; revert Hne'; case (norm e'); intro e''; [|now simpl].
- now case e''; [|intro e'''; case e'''..]. }
- rewrite of_int_norm.
- case_eq (Z.of_int e'); [|intro pe'..]; intro Hnpe';
- [now simpl; rewrite app_int_nil_r, norm_invol..|].
- case Nat.ltb_spec; intro Hpe'.
- * rewrite nb_digits_del_head; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply Nat.lt_le_incl].
- simpl.
- rewrite Z.sub_sub_distr, Z.sub_diag, Z.add_0_l.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- rewrite positive_nat_Z; simpl.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- rewrite app_int_del_tail_head; [|now apply Nat.lt_le_incl].
- now rewrite norm_invol, (proj2 (Nat.ltb_lt _ _) Hpe').
- * simpl.
- rewrite nb_digits_iter_D0.
- rewrite (Nat.sub_add _ _ Hpe').
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- rewrite positive_nat_Z; simpl.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- revert Hpe'.
- set (i' := norm (app_int i f)).
- case_eq i'; intros u Hu Hpe'.
- ++ simpl; unfold app; simpl.
- rewrite unorm_D0, unorm_iter_D0.
- assert (Hu' : unorm u = u).
- { generalize (f_equal norm Hu).
- unfold i'; rewrite norm_invol; fold i'.
- now simpl; rewrite Hu; intro H; injection H. }
- now rewrite Hu', (proj2 (Nat.ltb_ge _ _) Hpe').
- ++ simpl; rewrite nzhead_iter_D0.
- assert (Hu' : nzhead u = u).
- { generalize (f_equal norm Hu).
- unfold i'; rewrite norm_invol; fold i'.
- now rewrite Hu; simpl; case (nzhead u); [|intros u' H; injection H..]. }
- rewrite Hu'.
- assert (Hu'' : u <> Nil).
- { intro H; revert Hu; rewrite H; unfold i'.
- now case app_int; intro u'; [|simpl; case nzhead]. }
- set (m := match u with Nil => Pos zero | _ => _ end).
- assert (H : m = Neg u); [|rewrite H; clear m H].
- { now revert Hu''; unfold m; case u. }
- now rewrite (proj2 (Nat.ltb_ge _ _) Hpe').
+ case i as [ni|ni]; [now simpl|]; simpl.
+ case (uint_eq_dec (nzhead (app ni f)) Nil); intro Ha.
+ { now rewrite Ha, (nzhead_app_nil_l _ _ Ha). }
+ rewrite (unorm_nzhead _ Ha).
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (Neg (unorm ni)); [|now unfold m; revert Ha; case nzhead].
+ case (uint_eq_dec (nzhead ni) Nil); intro Hni.
+ { rewrite <-nzhead_app_nzhead, Hni, app_nil_l.
+ intro H; exfalso; revert H; apply le_not_lt, nb_digits_nzhead. }
+ clear m; set (m := match nzhead ni with Nil => _ | _ => _ end).
+ replace m with (Neg (nzhead ni)); [|now unfold m; revert Hni; case nzhead].
+ now rewrite (unorm_nzhead _ Hni).
+Qed.
+
+Lemma dnorm_i_exact' i f :
+ (nb_digits (unorm (app (abs i) f)) <= nb_digits f)%nat ->
+ match i with
+ | Pos i => Pos (unorm i)
+ | Neg i =>
+ match nzhead (app i f) with
+ | Nil => Pos zero
+ | _ => Neg (unorm i)
+ end
+ end =
+ match norm (app_int i f) with
+ | Pos _ => Pos zero
+ | Neg _ => Neg zero
+ end.
+Proof.
+ case i as [ni|ni]; simpl.
+ { now intro Hnb; rewrite (unorm_app_zero _ _ Hnb). }
+ unfold unorm.
+ case (uint_eq_dec (nzhead (app ni f)) Nil); intro Hn.
+ { now rewrite Hn. }
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (nzhead (app ni f)).
+ 2:{ now unfold m; revert Hn; case nzhead. }
+ clear m; set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (Neg (unorm ni)).
+ 2:{ now unfold m, unorm; revert Hn; case nzhead. }
+ clear m; set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (Neg (nzhead (app ni f))).
+ 2:{ now unfold m; revert Hn; case nzhead. }
+ rewrite <-(unorm_nzhead _ Hn).
+ now intro H; rewrite (unorm_app_zero _ _ H).
Qed.
-Lemma to_of (d:decimal) :
- to_decimal (of_decimal d) = Some (dnorme d)
- \/ to_decimal (of_decimal d) = Some (dnormf d).
+Lemma to_of (d:decimal) : to_decimal (of_decimal d) = Some (dnorm d).
Proof.
- unfold to_decimal.
- pose (t10 := fun y => ((y + y~0~0)~0)%positive).
- assert (H : exists e_den,
- Decimal.nztail (Pos.to_uint (Qden (of_decimal d))) = (D1 Nil, e_den)).
- { assert (H : forall p,
- Decimal.nztail (Pos.to_uint (Pos.iter t10 1%positive p))
- = (D1 Nil, Pos.to_nat p)).
- { intro p; rewrite Pos2Nat.inj_iter.
- fold (Nat.iter (Pos.to_nat p) t10 1%positive).
- induction (Pos.to_nat p); [now simpl|].
- rewrite DecimalPos.Unsigned.nat_iter_S.
- unfold Pos.to_uint.
- change (Pos.to_little_uint _)
- with (Unsigned.to_lu (10 * N.pos (Nat.iter n t10 1%positive))).
- rewrite Unsigned.to_ldec_tenfold.
- revert IHn; unfold Pos.to_uint.
- unfold Decimal.nztail; rewrite !rev_rev; simpl.
- set (f'' := _ (Pos.to_little_uint _)).
- now case f''; intros r n' H; inversion H. }
- case d; intros i f; [|intro e]; unfold of_decimal; simpl.
- - case (- Z.of_nat _)%Z; [|intro p..]; simpl; [now exists O..|].
- exists (Pos.to_nat p); apply H.
- - case (_ - _)%Z; [|intros p..]; simpl; [now exists O..|].
- exists (Pos.to_nat p); apply H. }
- generalize (DecimalPos.Unsigned.nztail_to_uint (Qden (of_decimal d))).
- destruct H as (e, He); rewrite He; clear He; simpl.
- assert (Hn1 : forall p, N.pos (Pos.iter t10 1%positive p) = 1%N -> False).
- { intro p.
- rewrite Pos2Nat.inj_iter.
- case_eq (Pos.to_nat p); [|now simpl].
- intro H; exfalso; apply (lt_irrefl O).
- rewrite <-H at 2; apply Pos2Nat.is_pos. }
- assert (Ht10inj : forall n m, t10 n = t10 m -> n = m).
- { intros n m H; generalize (f_equal Z.pos H); clear H.
- change (Z.pos (t10 n)) with (Z.mul 10 (Z.pos n)).
- change (Z.pos (t10 m)) with (Z.mul 10 (Z.pos m)).
- rewrite Z.mul_comm, (Z.mul_comm 10).
- intro H; generalize (f_equal (fun z => Z.div z 10) H); clear H.
- now rewrite !Z.div_mul; [|now simpl..]; intro H; inversion H. }
- assert (Hinj : forall n m,
- Nat.iter n t10 1%positive = Nat.iter m t10 1%positive -> n = m).
- { induction n; [now intro m; case m|].
- intro m; case m; [now simpl|]; clear m; intro m.
- rewrite !Unsigned.nat_iter_S.
- intro H; generalize (Ht10inj _ _ H); clear H; intro H.
- now rewrite (IHn _ H). }
- case e; clear e; [|intro e]; simpl; unfold of_decimal, dnormf, dnorme.
- - case d; clear d; intros i f; [|intro e]; simpl.
- + intro H; left; revert H.
- generalize (nb_digits_pos f).
- case f;
- [|now clear f; intro f; intros H1 H2; exfalso; revert H1 H2;
- case nb_digits; simpl;
- [intros H _; apply (lt_irrefl O), H|intros n _; apply Hn1]..].
- now intros _ _; simpl; rewrite to_of.
- + intro H; right; revert H.
- rewrite <-to_of, DecimalZ.of_to.
- set (emf := (_ - _)%Z).
- case_eq emf; [|intro pemf..].
- * now simpl; rewrite to_of.
- * set (r := DecimalExp _ _ _).
- set (m := match _ with Pos _ => _ | _ => r end).
- assert (H : m = r).
- { unfold m, Z.to_int.
- generalize (Unsigned.to_uint_nonzero pemf).
- now case Pos.to_uint; [|intro u; case u..]. }
- rewrite H; unfold r; clear H m r.
- rewrite DecimalZ.of_to.
- simpl Qnum.
- intros Hpemf _.
- apply f_equal; apply f_equal2; [|reflexivity].
- rewrite !Pos2Nat.inj_iter.
- set (n := _ pemf).
- fold (Nat.iter n (Z.mul 10) (Z.of_int (app_int i f))).
- fold (Nat.iter n D0 Nil).
- rewrite <-of_int_iter_D0, to_of.
- now rewrite norm_app_int_norm; [|induction n].
- * simpl Qden; intros _ H; exfalso; revert H; apply Hn1.
- - case d; clear d; intros i f; [|intro e']; simpl.
- + case_eq (nb_digits f); [|intros nf' Hnf'];
- [now simpl; intros _ H; exfalso; symmetry in H; revert H; apply Hn1|].
- unfold Z.of_nat, Z.opp.
- simpl Qden.
- intro H; injection H; clear H; unfold Pos.pow.
- rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (SuccNat2Pos.inj _ _ ((Pos2Nat.inj _ _ H))); clear H.
- intro He; rewrite <-He; clear e He.
- simpl Qnum.
- case Nat.ltb; [left|right].
- * now rewrite <-to_of, DecimalZ.of_to, to_of.
- * rewrite to_of.
- set (nif := norm _).
- set (anif := match nif with Pos i0 => i0 | _ => _ end).
- set (r := DecimalExp nif Nil _).
- set (m := match _ with Pos _ => _ | _ => r end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { now unfold m; rewrite <-to_of, DecimalZ.of_to. }
- rewrite <-to_of, !DecimalZ.of_to.
- fold anif.
- now rewrite SuccNat2Pos.id_succ.
- + set (nemf := (_ - _)%Z); intro H.
- assert (H' : exists pnemf, nemf = Z.neg pnemf); [|revert H].
- { revert H; case nemf; [|intro pnemf..]; [..|now intros _; exists pnemf];
- simpl Qden; intro H; exfalso; symmetry in H; revert H; apply Hn1. }
- destruct H' as (pnemf,Hpnemf); rewrite Hpnemf.
- simpl Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H.
- intro H; revert Hpnemf; rewrite H; clear pnemf H; intro Hnemf.
- simpl Qnum.
- case Nat.ltb; [left|right].
- * now rewrite <-to_of, DecimalZ.of_to, to_of.
- * rewrite to_of.
- set (nif := norm _).
- set (anif := match nif with Pos i0 => i0 | _ => _ end).
- set (r := DecimalExp nif Nil _).
- set (m := match _ with Pos _ => _ | _ => r end).
- assert (H : m = r); [|rewrite H; unfold m, r; clear m r H].
- { now unfold m; rewrite <-to_of, DecimalZ.of_to. }
- rewrite <-to_of, !DecimalZ.of_to.
- fold anif.
- now rewrite SuccNat2Pos.id_succ.
+ case d as [i f|i f e].
+ - unfold of_decimal; simpl; unfold IQmake_to_decimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_decimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 10).
+ rewrite nztail_to_uint_pow10, to_of.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ + rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ + rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ * rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ * rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
+ - unfold of_decimal; simpl.
+ rewrite <-to_of.
+ case (Z.of_int e); clear e; [|intro e..]; simpl.
+ + unfold IQmake_to_decimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_decimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 10).
+ rewrite nztail_to_uint_pow10, to_of.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ * rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ * rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ -- rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ -- rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
+ + unfold IQmake_to_decimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_decimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 10).
+ rewrite nztail_to_uint_pow10, to_of.
+ generalize (Unsigned.to_uint_nonzero e); intro He.
+ set (dnorm_i := match i with Pos _ => _ | _ => _ end).
+ set (m := match Pos.to_uint e with Nil => _ | _ => _ end).
+ replace m with (DecimalExp dnorm_i f (Pos (Pos.to_uint e))).
+ 2:{ now unfold m; revert He; case (Pos.to_uint e); [|intro u; case u|..]. }
+ clear m; unfold dnorm_i.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ * rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ * rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ -- rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ -- rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
+ + unfold IQmake_to_decimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_decimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 10).
+ rewrite nztail_to_uint_pow10, to_of.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ * rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ * rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ -- rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ -- rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
Qed.
(** Some consequences *)
@@ -478,84 +436,24 @@ Proof.
now intros d _ H1 H2; rewrite <-(H1 d eq_refl), <-(H2 d eq_refl).
Qed.
-Lemma to_decimal_surj d :
- exists q, to_decimal q = Some (dnorme d) \/ to_decimal q = Some (dnormf d).
+Lemma to_decimal_surj d : exists q, to_decimal q = Some (dnorm d).
Proof.
exists (of_decimal d). apply to_of.
Qed.
-Lemma of_decimal_dnorme d : of_decimal (dnorme d) = of_decimal d.
+Lemma of_decimal_dnorm d : of_decimal (dnorm d) = of_decimal d.
+Proof. now apply to_decimal_inj; rewrite !to_of; [|rewrite dnorm_involutive]. Qed.
+
+Lemma of_inj d d' : of_decimal d = of_decimal d' -> dnorm d = dnorm d'.
Proof.
- unfold of_decimal, dnorme.
- destruct d.
- - rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- case_eq (nb_digits f); [|intro nf]; intro Hnf.
- + now simpl; rewrite app_int_nil_r, <-DecimalZ.to_of, DecimalZ.of_to.
- + simpl; rewrite Z.sub_0_r.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- rewrite app_int_nil_r.
- now rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- - rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- set (emf := (_ - _)%Z).
- case_eq emf; [|intro pemf..]; intro Hemf.
- + now simpl; rewrite app_int_nil_r, <-DecimalZ.to_of, DecimalZ.of_to.
- + simpl.
- set (r := DecimalExp _ Nil _).
- set (m := match Pos.to_uint pemf with zero => _ | _ => r end).
- assert (H : m = r); [|rewrite H; unfold r; clear m r H].
- { generalize (Unsigned.to_uint_nonzero pemf).
- now unfold m; case Pos.to_uint; [|intro u; case u|..]. }
- simpl; rewrite Z.sub_0_r.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- rewrite app_int_nil_r.
- now rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- + simpl.
- unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
- rewrite app_int_nil_r.
- now rewrite <-DecimalZ.to_of, DecimalZ.of_to.
+ intro H.
+ apply (@f_equal _ _ (fun x => match x with Some x => x | _ => d end)
+ (Some (dnorm d)) (Some (dnorm d'))).
+ now rewrite <- !to_of, H.
Qed.
-Lemma of_decimal_dnormf d : of_decimal (dnormf d) = of_decimal d.
+Lemma of_iff d d' : of_decimal d = of_decimal d' <-> dnorm d = dnorm d'.
Proof.
- rewrite <-(of_decimal_dnorme d).
- unfold of_decimal, dnormf.
- assert (H : match dnorme d with Decimal _ f | DecimalExp _ f _ => f end = Nil).
- { now unfold dnorme; destruct d;
- (case norm; intro d; [case d; [|intro u; case u|..]|]). }
- revert H; generalize (dnorme d); clear d; intro d.
- destruct d; intro H; rewrite H; clear H; [now simpl|].
- case (Z.of_int e); clear e; [|intro e..].
- - now simpl.
- - simpl.
- rewrite app_int_nil_r.
- apply f_equal2; [|reflexivity].
- rewrite app_int_nil_r.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- rewrite !Pos2Nat.inj_iter.
- fold (Nat.iter (Pos.to_nat e) D0 Nil).
- now rewrite of_int_iter_D0.
- - simpl.
- set (ai := match i with Pos _ => _ | _ => _ end).
- rewrite app_int_nil_r.
- case Nat.ltb_spec; intro Hei; simpl.
- + rewrite nb_digits_del_head; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply Nat.le_sub_l].
- rewrite Nat2Z.inj_sub; [|now apply le_Sn_le].
- rewrite Z.sub_sub_distr, Z.sub_diag; simpl.
- rewrite positive_nat_Z; simpl.
- now revert Hei; unfold ai; case i; clear i ai; intros i Hei; simpl;
- (rewrite app_del_tail_head; [|now apply le_Sn_le]).
- + set (n := nb_digits _).
- assert (H : (n = Pos.to_nat e - nb_digits ai + nb_digits ai)%nat).
- { unfold n; induction (_ - _)%nat; [now simpl|].
- now rewrite Unsigned.nat_iter_S; simpl; rewrite IHn0. }
- rewrite H; clear n H.
- rewrite Nat2Z.inj_add, (Nat2Z.inj_sub _ _ Hei).
- rewrite <-Z.sub_sub_distr, Z.sub_diag, Z.sub_0_r.
- rewrite positive_nat_Z; simpl.
- rewrite <-(DecimalZ.of_to (Z.of_int (app_int _ _))), DecimalZ.to_of.
- rewrite <-(DecimalZ.of_to (Z.of_int i)), DecimalZ.to_of.
- apply f_equal2; [|reflexivity]; apply f_equal.
- now unfold ai; case i; clear i ai Hei; intro i;
- (induction (_ - _)%nat; [|rewrite <-IHn]).
+ split. apply of_inj. intros E. rewrite <- of_decimal_dnorm, E.
+ apply of_decimal_dnorm.
Qed.
diff --git a/theories/Numbers/DecimalR.v b/theories/Numbers/DecimalR.v
new file mode 100644
index 0000000000..9b65a7dc20
--- /dev/null
+++ b/theories/Numbers/DecimalR.v
@@ -0,0 +1,312 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(** * DecimalR
+
+ Proofs that conversions between decimal numbers and [R]
+ are bijections. *)
+
+Require Import Decimal DecimalFacts DecimalPos DecimalZ DecimalQ Rdefinitions.
+
+Lemma of_IQmake_to_decimal num den :
+ match IQmake_to_decimal num den with
+ | None => True
+ | Some (DecimalExp _ _ _) => False
+ | Some (Decimal i f) =>
+ of_decimal (Decimal i f) = IRQ (QArith_base.Qmake num den)
+ end.
+Proof.
+ unfold IQmake_to_decimal.
+ case (Pos.eq_dec den 1); [now intros->|intro Hden].
+ assert (Hf : match QArith_base.IQmake_to_decimal num den with
+ | Some (Decimal i f) => f <> Nil
+ | _ => True
+ end).
+ { unfold QArith_base.IQmake_to_decimal; simpl.
+ generalize (Unsigned.nztail_to_uint den).
+ case Decimal.nztail as [den' e_den'].
+ case den'; [now simpl|now simpl| |now simpl..]; clear den'; intro den'.
+ case den'; [ |now simpl..]; clear den'.
+ case e_den' as [|e_den']; [now simpl; intros H _; apply Hden; injection H|].
+ intros _.
+ case Nat.ltb_spec; intro He_den'.
+ - apply del_head_nonnil.
+ revert He_den'; case nb_digits as [|n]; [now simpl|].
+ now intro H; simpl; apply le_lt_n_Sm, Nat.le_sub_l.
+ - apply nb_digits_n0.
+ now rewrite nb_digits_iter_D0, Nat.sub_add. }
+ replace (match den with 1%positive => _ | _ => _ end)
+ with (QArith_base.IQmake_to_decimal num den); [|now revert Hden; case den].
+ generalize (of_IQmake_to_decimal num den).
+ case QArith_base.IQmake_to_decimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ unfold of_decimal; simpl.
+ intro H; injection H; clear H; intros <-.
+ intro H; generalize (f_equal QArith_base.IZ_to_Z H); clear H.
+ rewrite !IZ_to_Z_IZ_of_Z; intro H; injection H; clear H; intros<-.
+ now revert Hf; case f.
+Qed.
+
+Lemma of_to (q:IR) : forall d, to_decimal q = Some d -> of_decimal d = q.
+Proof.
+ intro d.
+ case q as [z|q|r r'|r r']; simpl.
+ - case z as [z p| |p|p].
+ + now simpl.
+ + now simpl; intro H; injection H; clear H; intros<-.
+ + simpl; intro H; injection H; clear H; intros<-.
+ now unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to.
+ + simpl; intro H; injection H; clear H; intros<-.
+ now unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to.
+ - case q as [num den].
+ generalize (of_IQmake_to_decimal num den).
+ case IQmake_to_decimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ now intros H H'; injection H'; intros<-.
+ - case r as [z|q| |]; [|case q as[num den]|now simpl..];
+ (case r' as [z'| | |]; [|now simpl..]);
+ (case z' as [p e| | |]; [|now simpl..]).
+ + case (Z.eq_dec p 10); [intros->|intro Hp].
+ 2:{ revert Hp; case p; [now simpl|intro d0..];
+ (case d0; [intro d1..|]; [now simpl| |now simpl];
+ case d1; [intro d2..|]; [|now simpl..];
+ case d2; [intro d3..|]; [now simpl| |now simpl];
+ now case d3). }
+ case z as [| |p|p]; [now simpl|..]; intro H; injection H; intros<-.
+ * now unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to.
+ * unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to; simpl.
+ now rewrite Unsigned.of_to.
+ * unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to; simpl.
+ now rewrite Unsigned.of_to.
+ + case (Z.eq_dec p 10); [intros->|intro Hp].
+ 2:{ revert Hp; case p; [now simpl|intro d0..];
+ (case d0; [intro d1..|]; [now simpl| |now simpl];
+ case d1; [intro d2..|]; [|now simpl..];
+ case d2; [intro d3..|]; [now simpl| |now simpl];
+ now case d3). }
+ generalize (of_IQmake_to_decimal num den).
+ case IQmake_to_decimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros H H'; injection H'; clear H'; intros<-.
+ unfold of_decimal; simpl.
+ change (match f with Nil => _ | _ => _ end) with (of_decimal (Decimal i f)).
+ rewrite H; clear H.
+ now unfold Z.of_uint; rewrite Unsigned.of_to.
+ - case r as [z|q| |]; [|case q as[num den]|now simpl..];
+ (case r' as [z'| | |]; [|now simpl..]);
+ (case z' as [p e| | |]; [|now simpl..]).
+ + case (Z.eq_dec p 10); [intros->|intro Hp].
+ 2:{ revert Hp; case p; [now simpl|intro d0..];
+ (case d0; [intro d1..|]; [now simpl| |now simpl];
+ case d1; [intro d2..|]; [|now simpl..];
+ case d2; [intro d3..|]; [now simpl| |now simpl];
+ now case d3). }
+ case z as [| |p|p]; [now simpl|..]; intro H; injection H; intros<-.
+ * now unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to.
+ * unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to; simpl.
+ now rewrite Unsigned.of_to.
+ * unfold of_decimal; simpl; unfold Z.of_uint; rewrite Unsigned.of_to; simpl.
+ now rewrite Unsigned.of_to.
+ + case (Z.eq_dec p 10); [intros->|intro Hp].
+ 2:{ revert Hp; case p; [now simpl|intro d0..];
+ (case d0; [intro d1..|]; [now simpl| |now simpl];
+ case d1; [intro d2..|]; [|now simpl..];
+ case d2; [intro d3..|]; [now simpl| |now simpl];
+ now case d3). }
+ generalize (of_IQmake_to_decimal num den).
+ case IQmake_to_decimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros H H'; injection H'; clear H'; intros<-.
+ unfold of_decimal; simpl.
+ change (match f with Nil => _ | _ => _ end) with (of_decimal (Decimal i f)).
+ rewrite H; clear H.
+ now unfold Z.of_uint; rewrite Unsigned.of_to.
+Qed.
+
+Lemma to_of (d:decimal) : to_decimal (of_decimal d) = Some (dnorm d).
+Proof.
+ case d as [i f|i f e].
+ - unfold of_decimal; simpl.
+ case (uint_eq_dec f Nil); intro Hf.
+ + rewrite Hf; clear f Hf.
+ unfold to_decimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, DecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ + set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_decimal; simpl.
+ unfold IQmake_to_decimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_decimal (Z.of_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_decimal, n; simpl.
+ rewrite nztail_to_uint_pow10.
+ clear r; set (r := if _ <? _ then Some (Decimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite DecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ * rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ * rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+ - unfold of_decimal; simpl.
+ rewrite <-(DecimalZ.to_of e).
+ case (Z.of_int e); clear e; [|intro e..]; simpl.
+ + case (uint_eq_dec f Nil); intro Hf.
+ * rewrite Hf; clear f Hf.
+ unfold to_decimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, DecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ * set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_decimal; simpl.
+ unfold IQmake_to_decimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_decimal (Z.of_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_decimal, n; simpl.
+ rewrite nztail_to_uint_pow10.
+ clear r; set (r := if _ <? _ then Some (Decimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite DecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ -- rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ -- rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+ + set (i' := match i with Pos _ => _ | _ => _ end).
+ set (m := match Pos.to_uint e with Nil => _ | _ => _ end).
+ replace m with (DecimalExp i' f (Pos (Pos.to_uint e))).
+ 2:{ unfold m; generalize (Unsigned.to_uint_nonzero e).
+ now case Pos.to_uint; [|intro u; case u|..]. }
+ unfold i'; clear i' m.
+ case (uint_eq_dec f Nil); intro Hf.
+ * rewrite Hf; clear f Hf.
+ unfold to_decimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, DecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ * set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_decimal; simpl.
+ unfold IQmake_to_decimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_decimal (Z.of_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_decimal, n; simpl.
+ rewrite nztail_to_uint_pow10.
+ clear r; set (r := if _ <? _ then Some (Decimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite DecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ -- rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ -- rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+ + case (uint_eq_dec f Nil); intro Hf.
+ * rewrite Hf; clear f Hf.
+ unfold to_decimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, DecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ * set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_decimal; simpl.
+ unfold IQmake_to_decimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_decimal (Z.of_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_decimal, n; simpl.
+ rewrite nztail_to_uint_pow10.
+ clear r; set (r := if _ <? _ then Some (Decimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite DecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ -- rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ -- rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+Qed.
+
+(** Some consequences *)
+
+Lemma to_decimal_inj q q' :
+ to_decimal q <> None -> to_decimal q = to_decimal q' -> q = q'.
+Proof.
+ intros Hnone EQ.
+ generalize (of_to q) (of_to q').
+ rewrite <-EQ.
+ revert Hnone; case to_decimal; [|now simpl].
+ now intros d _ H1 H2; rewrite <-(H1 d eq_refl), <-(H2 d eq_refl).
+Qed.
+
+Lemma to_decimal_surj d : exists q, to_decimal q = Some (dnorm d).
+Proof.
+ exists (of_decimal d). apply to_of.
+Qed.
+
+Lemma of_decimal_dnorm d : of_decimal (dnorm d) = of_decimal d.
+Proof. now apply to_decimal_inj; rewrite !to_of; [|rewrite dnorm_involutive]. Qed.
+
+Lemma of_inj d d' : of_decimal d = of_decimal d' -> dnorm d = dnorm d'.
+Proof.
+ intro H.
+ apply (@f_equal _ _ (fun x => match x with Some x => x | _ => d end)
+ (Some (dnorm d)) (Some (dnorm d'))).
+ now rewrite <- !to_of, H.
+Qed.
+
+Lemma of_iff d d' : of_decimal d = of_decimal d' <-> dnorm d = dnorm d'.
+Proof.
+ split. apply of_inj. intros E. rewrite <- of_decimal_dnorm, E.
+ apply of_decimal_dnorm.
+Qed.
diff --git a/theories/Numbers/DecimalZ.v b/theories/Numbers/DecimalZ.v
index 69d8073fc7..faaf8a3932 100644
--- a/theories/Numbers/DecimalZ.v
+++ b/theories/Numbers/DecimalZ.v
@@ -79,9 +79,11 @@ Qed.
Lemma of_uint_iter_D0 d n :
Z.of_uint (app d (Nat.iter n D0 Nil)) = Nat.iter n (Z.mul 10) (Z.of_uint d).
Proof.
- unfold Z.of_uint.
- unfold app; rewrite <-rev_revapp.
- rewrite Unsigned.of_lu_rev, Unsigned.of_lu_revapp.
+ rewrite <-(rev_rev (app _ _)), <-(of_list_to_list (rev (app _ _))).
+ rewrite rev_spec, app_spec, List.rev_app_distr.
+ rewrite <-!rev_spec, <-app_spec, of_list_to_list.
+ unfold Z.of_uint; rewrite Unsigned.of_lu_rev.
+ unfold app; rewrite Unsigned.of_lu_revapp, !rev_rev.
rewrite <-!Unsigned.of_lu_rev, !rev_rev.
assert (H' : Pos.of_uint (Nat.iter n D0 Nil) = 0%N).
{ now induction n; [|rewrite Unsigned.nat_iter_S]. }
@@ -100,3 +102,22 @@ Proof.
- rewrite of_uint_iter_D0; induction n; [now simpl|].
rewrite !Unsigned.nat_iter_S, <-IHn; ring.
Qed.
+
+Lemma nztail_to_uint_pow10 n :
+ Decimal.nztail (Pos.to_uint (Nat.iter n (Pos.mul 10) 1%positive))
+ = (D1 Nil, n).
+Proof.
+ case n as [|n]; [now simpl|].
+ rewrite <-(Nat2Pos.id (S n)); [|now simpl].
+ generalize (Pos.of_nat (S n)); clear n; intro p.
+ induction (Pos.to_nat p); [now simpl|].
+ rewrite Unsigned.nat_iter_S.
+ unfold Pos.to_uint.
+ change (Pos.to_little_uint _)
+ with (Unsigned.to_lu (10 * N.pos (Nat.iter n (Pos.mul 10) 1%positive))).
+ rewrite Unsigned.to_ldec_tenfold.
+ revert IHn; unfold Pos.to_uint.
+ unfold Decimal.nztail; rewrite !rev_rev; simpl.
+ set (f'' := _ (Pos.to_little_uint _)).
+ now case f''; intros r n' H; inversion H.
+Qed.
diff --git a/theories/Numbers/HexadecimalFacts.v b/theories/Numbers/HexadecimalFacts.v
index 7328b2303d..c624b4e6b9 100644
--- a/theories/Numbers/HexadecimalFacts.v
+++ b/theories/Numbers/HexadecimalFacts.v
@@ -10,136 +10,437 @@
(** * HexadecimalFacts : some facts about Hexadecimal numbers *)
-Require Import Hexadecimal Arith.
+Require Import Hexadecimal Arith ZArith.
+
+Variant digits :=
+ | d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 | d8 | d9
+ | da | db | dc | dd | de | df.
+
+Fixpoint to_list (u : uint) : list digits :=
+ match u with
+ | Nil => nil
+ | D0 u => cons d0 (to_list u)
+ | D1 u => cons d1 (to_list u)
+ | D2 u => cons d2 (to_list u)
+ | D3 u => cons d3 (to_list u)
+ | D4 u => cons d4 (to_list u)
+ | D5 u => cons d5 (to_list u)
+ | D6 u => cons d6 (to_list u)
+ | D7 u => cons d7 (to_list u)
+ | D8 u => cons d8 (to_list u)
+ | D9 u => cons d9 (to_list u)
+ | Da u => cons da (to_list u)
+ | Db u => cons db (to_list u)
+ | Dc u => cons dc (to_list u)
+ | Dd u => cons dd (to_list u)
+ | De u => cons de (to_list u)
+ | Df u => cons df (to_list u)
+ end.
+
+Fixpoint of_list (l : list digits) : uint :=
+ match l with
+ | nil => Nil
+ | cons d0 l => D0 (of_list l)
+ | cons d1 l => D1 (of_list l)
+ | cons d2 l => D2 (of_list l)
+ | cons d3 l => D3 (of_list l)
+ | cons d4 l => D4 (of_list l)
+ | cons d5 l => D5 (of_list l)
+ | cons d6 l => D6 (of_list l)
+ | cons d7 l => D7 (of_list l)
+ | cons d8 l => D8 (of_list l)
+ | cons d9 l => D9 (of_list l)
+ | cons da l => Da (of_list l)
+ | cons db l => Db (of_list l)
+ | cons dc l => Dc (of_list l)
+ | cons dd l => Dd (of_list l)
+ | cons de l => De (of_list l)
+ | cons df l => Df (of_list l)
+ end.
-Scheme Equality for uint.
+Lemma of_list_to_list u : of_list (to_list u) = u.
+Proof. now induction u; [|simpl; rewrite IHu..]. Qed.
-Scheme Equality for int.
+Lemma to_list_of_list l : to_list (of_list l) = l.
+Proof. now induction l as [|h t IHl]; [|case h; simpl; rewrite IHl]. Qed.
-Lemma rev_revapp d d' :
- rev (revapp d d') = revapp d' d.
+Lemma to_list_inj u u' : to_list u = to_list u' -> u = u'.
Proof.
- revert d'. induction d; simpl; intros; now rewrite ?IHd.
+ now intro H; rewrite <-(of_list_to_list u), <-(of_list_to_list u'), H.
Qed.
-Lemma rev_rev d : rev (rev d) = d.
+Lemma of_list_inj u u' : of_list u = of_list u' -> u = u'.
Proof.
- apply rev_revapp.
+ now intro H; rewrite <-(to_list_of_list u), <-(to_list_of_list u'), H.
Qed.
-Lemma revapp_rev_nil d : revapp (rev d) Nil = d.
-Proof. now fold (rev (rev d)); rewrite rev_rev. Qed.
+Lemma nb_digits_spec u : nb_digits u = length (to_list u).
+Proof. now induction u; [|simpl; rewrite IHu..]. Qed.
-Lemma app_nil_r d : app d Nil = d.
-Proof. now unfold app; rewrite revapp_rev_nil. Qed.
+Fixpoint lnzhead l :=
+ match l with
+ | nil => nil
+ | cons d l' =>
+ match d with
+ | d0 => lnzhead l'
+ | _ => l
+ end
+ end.
-Lemma app_int_nil_r d : app_int d Nil = d.
-Proof. now case d; intro d'; simpl; rewrite app_nil_r. Qed.
+Lemma nzhead_spec u : to_list (nzhead u) = lnzhead (to_list u).
+Proof. now induction u; [|simpl; rewrite IHu|..]. Qed.
+
+Definition lzero := cons d0 nil.
+
+Definition lunorm l :=
+ match lnzhead l with
+ | nil => lzero
+ | d => d
+ end.
+
+Lemma unorm_spec u : to_list (unorm u) = lunorm (to_list u).
+Proof. now unfold unorm, lunorm; rewrite <-nzhead_spec; case (nzhead u). Qed.
+
+Lemma revapp_spec d d' :
+ to_list (revapp d d') = List.rev_append (to_list d) (to_list d').
+Proof. now revert d'; induction d; intro d'; [|simpl; rewrite IHd..]. Qed.
+
+Lemma rev_spec d : to_list (rev d) = List.rev (to_list d).
+Proof. now unfold rev; rewrite revapp_spec, List.rev_alt; simpl. Qed.
+
+Lemma app_spec d d' :
+ to_list (app d d') = Datatypes.app (to_list d) (to_list d').
+Proof.
+ unfold app.
+ now rewrite revapp_spec, List.rev_append_rev, rev_spec, List.rev_involutive.
+Qed.
-Lemma revapp_revapp_1 d d' d'' :
- nb_digits d <= 1 ->
- revapp (revapp d d') d'' = revapp d' (revapp d d'').
+Definition lnztail l :=
+ let fix aux l_rev :=
+ match l_rev with
+ | cons d0 l_rev => let (r, n) := aux l_rev in pair r (S n)
+ | _ => pair l_rev O
+ end in
+ let (r, n) := aux (List.rev l) in pair (List.rev r) n.
+
+Lemma nztail_spec d :
+ let (r, n) := nztail d in
+ let (r', n') := lnztail (to_list d) in
+ to_list r = r' /\ n = n'.
Proof.
- now case d; clear d; intro d;
- [|case d; clear d; intro d;
- [|simpl; case nb_digits; [|intros n]; intros Hn; exfalso;
- [apply (Nat.nle_succ_diag_l _ Hn)|
- apply (Nat.nle_succ_0 _ (le_S_n _ _ Hn))]..]..].
+ unfold nztail, lnztail.
+ set (f := fix aux d_rev := match d_rev with
+ | D0 d_rev => let (r, n) := aux d_rev in (r, S n)
+ | _ => (d_rev, 0) end).
+ set (f' := fix aux (l_rev : list digits) : list digits * nat :=
+ match l_rev with
+ | cons d0 l_rev => let (r, n) := aux l_rev in (r, S n)
+ | _ => (l_rev, 0)
+ end).
+ rewrite <-(of_list_to_list (rev d)), rev_spec.
+ induction (List.rev _) as [|h t IHl]; [now simpl|].
+ case h; simpl; [|now rewrite rev_spec; simpl; rewrite to_list_of_list..].
+ now revert IHl; case f; intros r n; case f'; intros r' n' [-> ->].
Qed.
-Lemma nb_digits_pos d : d <> Nil -> 0 < nb_digits d.
-Proof. now case d; [|intros d' _; apply Nat.lt_0_succ..]. Qed.
+Lemma del_head_spec_0 d : del_head 0 d = d.
+Proof. now simpl. Qed.
-Lemma nb_digits_revapp d d' :
- nb_digits (revapp d d') = nb_digits d + nb_digits d'.
+Lemma del_head_spec_small n d :
+ n <= length (to_list d) -> to_list (del_head n d) = List.skipn n (to_list d).
Proof.
- now revert d'; induction d; [|intro d'; simpl; rewrite IHd; simpl..].
+ revert d; induction n as [|n IHn]; intro d; [now simpl|].
+ now case d; [|intros d' H; apply IHn, le_S_n..].
Qed.
-Lemma nb_digits_rev u : nb_digits (rev u) = nb_digits u.
-Proof. now unfold rev; rewrite nb_digits_revapp. Qed.
+Lemma del_head_spec_large n d : length (to_list d) < n -> del_head n d = zero.
+Proof.
+ revert d; induction n; intro d; [now case d|].
+ now case d; [|intro d'; simpl; intro H; rewrite (IHn _ (lt_S_n _ _ H))..].
+Qed.
-Lemma nb_digits_nzhead u : nb_digits (nzhead u) <= nb_digits u.
-Proof. now induction u; [|apply le_S|..]. Qed.
+Lemma nb_digits_0 d : nb_digits d = 0 -> d = Nil.
+Proof.
+ rewrite nb_digits_spec, <-(of_list_to_list d).
+ now case (to_list d) as [|h t]; [|rewrite to_list_of_list].
+Qed.
+
+Lemma nb_digits_n0 d : nb_digits d <> 0 -> d <> Nil.
+Proof. now case d; [|intros u _..]. Qed.
Lemma nb_digits_iter_D0 n d :
nb_digits (Nat.iter n D0 d) = n + nb_digits d.
Proof. now induction n; simpl; [|rewrite IHn]. Qed.
-Fixpoint nth n u :=
- match n with
- | O =>
- match u with
- | Nil => Nil
- | D0 d => D0 Nil
- | D1 d => D1 Nil
- | D2 d => D2 Nil
- | D3 d => D3 Nil
- | D4 d => D4 Nil
- | D5 d => D5 Nil
- | D6 d => D6 Nil
- | D7 d => D7 Nil
- | D8 d => D8 Nil
- | D9 d => D9 Nil
- | Da d => Da Nil
- | Db d => Db Nil
- | Dc d => Dc Nil
- | Dd d => Dd Nil
- | De d => De Nil
- | Df d => Df Nil
- end
- | S n =>
- match u with
- | Nil => Nil
- | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d
- | Da d | Db d | Dc d | Dd d | De d | Df d =>
- nth n d
- end
- end.
+Lemma length_lnzhead l : length (lnzhead l) <= length l.
+Proof. now induction l as [|h t IHl]; [|case h; [apply le_S|..]]. Qed.
+
+Lemma nb_digits_nzhead u : nb_digits (nzhead u) <= nb_digits u.
+Proof. now induction u; [|apply le_S|..]. Qed.
-Lemma nb_digits_nth n u : nb_digits (nth n u) <= 1.
-Proof.
- revert u; induction n.
- - now intro u; case u; [apply Nat.le_0_1|..].
- - intro u; case u; [apply Nat.le_0_1|intro u'; apply IHn..].
-Qed.
-
-Lemma nth_revapp_r n d d' :
- nb_digits d <= n ->
- nth n (revapp d d') = nth (n - nb_digits d) d'.
-Proof.
- revert d d'; induction n; intro d.
- - now case d; intro d';
- [case d'|intros d'' H; exfalso; revert H; apply Nat.nle_succ_0..].
- - now induction d;
- [intro d'; case d'|
- intros d' H;
- simpl revapp; rewrite IHd; [|now apply le_Sn_le];
- rewrite Nat.sub_succ_l; [|now apply le_S_n];
- simpl; rewrite <-(IHn _ _ (le_S_n _ _ H))..].
-Qed.
-
-Lemma nth_revapp_l n d d' :
- n < nb_digits d ->
- nth n (revapp d d') = nth (nb_digits d - n - 1) d.
-Proof.
- revert d d'; induction n; intro d.
- - rewrite Nat.sub_0_r.
- now induction d;
- [|intros d' _; simpl revapp;
- revert IHd; case d; clear d; [|intro d..]; intro IHd;
- [|rewrite IHd; [simpl nb_digits; rewrite (Nat.sub_succ_l _ (S _))|];
- [|apply le_n_S, Nat.le_0_l..]..]..].
- - now induction d;
- [|intros d' H;
- simpl revapp; simpl nb_digits;
- simpl in H; generalize (lt_S_n _ _ H); clear H; intro H;
- case (le_lt_eq_dec _ _ H); clear H; intro H;
- [rewrite (IHd _ H), Nat.sub_succ_l;
- [rewrite Nat.sub_succ_l; [|apply Nat.le_add_le_sub_r]|
- apply le_Sn_le]|
- rewrite nth_revapp_r; rewrite <-H;
- [rewrite Nat.sub_succ, Nat.sub_succ_l; [rewrite !Nat.sub_diag|]|]]..].
+Lemma unorm_nzhead u : nzhead u <> Nil -> unorm u = nzhead u.
+Proof. now unfold unorm; case nzhead. Qed.
+
+Lemma nb_digits_unorm u : u <> Nil -> nb_digits (unorm u) <= nb_digits u.
+Proof.
+ intro Hu; case (uint_eq_dec (nzhead u) Nil).
+ { unfold unorm; intros ->; simpl.
+ now revert Hu; case u; [|intros u' _; apply le_n_S, Nat.le_0_l..]. }
+ intro H; rewrite (unorm_nzhead _ H); apply nb_digits_nzhead.
+Qed.
+
+Lemma nb_digits_rev d : nb_digits (rev d) = nb_digits d.
+Proof. now rewrite !nb_digits_spec, rev_spec, List.rev_length. Qed.
+
+Lemma nb_digits_del_head_sub d n :
+ n <= nb_digits d ->
+ nb_digits (del_head (nb_digits d - n) d) = n.
+Proof.
+ rewrite !nb_digits_spec; intro Hn.
+ rewrite del_head_spec_small; [|now apply Nat.le_sub_l].
+ rewrite List.skipn_length, <-(Nat2Z.id (_ - _)).
+ rewrite Nat2Z.inj_sub; [|now apply Nat.le_sub_l].
+ rewrite (Nat2Z.inj_sub _ _ Hn).
+ rewrite Z.sub_sub_distr, Z.sub_diag; apply Nat2Z.id.
+Qed.
+
+Lemma unorm_D0 u : unorm (D0 u) = unorm u.
+Proof. reflexivity. Qed.
+
+Lemma app_nil_l d : app Nil d = d.
+Proof. now simpl. Qed.
+
+Lemma app_nil_r d : app d Nil = d.
+Proof. now apply to_list_inj; rewrite app_spec, List.app_nil_r. Qed.
+
+Lemma abs_app_int d d' : abs (app_int d d') = app (abs d) d'.
+Proof. now case d. Qed.
+
+Lemma abs_norm d : abs (norm d) = unorm (abs d).
+Proof. now case d as [u|u]; [|simpl; unfold unorm; case nzhead]. Qed.
+
+Lemma iter_D0_nzhead d :
+ Nat.iter (nb_digits d - nb_digits (nzhead d)) D0 (nzhead d) = d.
+Proof.
+ induction d; [now simpl| |now rewrite Nat.sub_diag..].
+ simpl nzhead; simpl nb_digits.
+ rewrite (Nat.sub_succ_l _ _ (nb_digits_nzhead _)).
+ now rewrite <-IHd at 4.
+Qed.
+
+Lemma iter_D0_unorm d :
+ d <> Nil ->
+ Nat.iter (nb_digits d - nb_digits (unorm d)) D0 (unorm d) = d.
+Proof.
+ case (uint_eq_dec (nzhead d) Nil); intro Hn.
+ { unfold unorm; rewrite Hn; simpl; intro H.
+ revert H Hn; induction d; [now simpl|intros _|now intros _..].
+ case (uint_eq_dec d Nil); simpl; intros H Hn; [now rewrite H|].
+ rewrite Nat.sub_0_r, (le_plus_minus 1 (nb_digits d)).
+ { now simpl; rewrite IHd. }
+ revert H; case d; [now simpl|intros u _; apply le_n_S, Nat.le_0_l..]. }
+ intros _; rewrite (unorm_nzhead _ Hn); apply iter_D0_nzhead.
+Qed.
+
+Lemma nzhead_app_l d d' :
+ nb_digits d' < nb_digits (nzhead (app d d')) ->
+ nzhead (app d d') = app (nzhead d) d'.
+Proof.
+ intro Hl; apply to_list_inj; revert Hl.
+ rewrite !nb_digits_spec, app_spec, !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl].
+ { now simpl; intro H; exfalso; revert H; apply le_not_lt, length_lnzhead. }
+ rewrite <-List.app_comm_cons.
+ now case h; [simpl; intro Hl; apply IHl|..].
+Qed.
+
+Lemma nzhead_app_r d d' :
+ nb_digits (nzhead (app d d')) <= nb_digits d' ->
+ nzhead (app d d') = nzhead d'.
+Proof.
+ intro Hl; apply to_list_inj; revert Hl.
+ rewrite !nb_digits_spec, !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl]; [now simpl|].
+ rewrite <-List.app_comm_cons.
+ now case h; [| simpl; rewrite List.app_length; intro Hl; exfalso; revert Hl;
+ apply le_not_lt, le_plus_r..].
+Qed.
+
+Lemma nzhead_app_nil_r d d' : nzhead (app d d') = Nil -> nzhead d' = Nil.
+Proof.
+now intro H; generalize H; rewrite nzhead_app_r; [|rewrite H; apply Nat.le_0_l].
+Qed.
+
+Lemma nzhead_app_nil d d' :
+ nb_digits (nzhead (app d d')) <= nb_digits d' -> nzhead d = Nil.
+Proof.
+ intro H; apply to_list_inj; revert H.
+ rewrite !nb_digits_spec, !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl]; [now simpl|].
+ now case h; [now simpl|..];
+ simpl;intro H; exfalso; revert H; apply le_not_lt;
+ rewrite List.app_length; apply le_plus_r.
+Qed.
+
+Lemma nzhead_app_nil_l d d' : nzhead (app d d') = Nil -> nzhead d = Nil.
+Proof.
+ intro H; apply to_list_inj; generalize (f_equal to_list H); clear H.
+ rewrite !nzhead_spec, app_spec.
+ induction (to_list d) as [|h t IHl]; [now simpl|].
+ now rewrite <-List.app_comm_cons; case h.
+Qed.
+
+Lemma unorm_app_zero d d' :
+ nb_digits (unorm (app d d')) <= nb_digits d' -> unorm d = zero.
+Proof.
+ unfold unorm.
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { now intro Hn; rewrite Hn, (nzhead_app_nil_l _ _ Hn). }
+ intro H; fold (unorm (app d d')); rewrite (unorm_nzhead _ H); intro H'.
+ case (uint_eq_dec (nzhead d) Nil); [now intros->|].
+ intro H''; fold (unorm d); rewrite (unorm_nzhead _ H'').
+ exfalso; apply H''; revert H'; apply nzhead_app_nil.
+Qed.
+
+Lemma app_int_nil_r d : app_int d Nil = d.
+Proof.
+ now case d; intro d'; simpl;
+ rewrite <-(of_list_to_list (app _ _)), app_spec;
+ rewrite List.app_nil_r, of_list_to_list.
+Qed.
+
+Lemma unorm_app_l d d' :
+ nb_digits d' < nb_digits (unorm (app d d')) ->
+ unorm (app d d') = app (unorm d) d'.
+Proof.
+ case (uint_eq_dec d' Nil); [now intros->; rewrite !app_nil_r|intro Hd'].
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { unfold unorm; intros->; simpl; intro H; exfalso; revert H; apply le_not_lt.
+ now revert Hd'; case d'; [|intros d'' _; apply le_n_S, Peano.le_0_n..]. }
+ intro Ha; rewrite (unorm_nzhead _ Ha).
+ intro Hn; generalize Hn; rewrite (nzhead_app_l _ _ Hn).
+ rewrite !nb_digits_spec, app_spec, List.app_length.
+ case (uint_eq_dec (nzhead d) Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply Nat.lt_irrefl. }
+ now intro H; rewrite (unorm_nzhead _ H).
+Qed.
+
+Lemma unorm_app_r d d' :
+ nb_digits (unorm (app d d')) <= nb_digits d' ->
+ unorm (app d d') = unorm d'.
+Proof.
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { now unfold unorm; intro H; rewrite H, (nzhead_app_nil_r _ _ H). }
+ intro Ha; rewrite (unorm_nzhead _ Ha).
+ case (uint_eq_dec (nzhead d') Nil).
+ { now intros H H'; exfalso; apply Ha; rewrite nzhead_app_r. }
+ intro Hd'; rewrite (unorm_nzhead _ Hd'); apply nzhead_app_r.
+Qed.
+
+Lemma norm_app_int d d' :
+ nb_digits d' < nb_digits (unorm (app (abs d) d')) ->
+ norm (app_int d d') = app_int (norm d) d'.
+Proof.
+ case (uint_eq_dec d' Nil); [now intros->; rewrite !app_int_nil_r|intro Hd'].
+ case d as [d|d]; [now simpl; intro H; apply f_equal, unorm_app_l|].
+ simpl; unfold unorm.
+ case (uint_eq_dec (nzhead (app d d')) Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply le_not_lt.
+ now revert Hd'; case d'; [|intros d'' _; apply le_n_S, Peano.le_0_n..]. }
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ intro Ha.
+ replace m with (nzhead (app d d')).
+ 2:{ now unfold m; revert Ha; case nzhead. }
+ intro Hn; generalize Hn; rewrite (nzhead_app_l _ _ Hn).
+ case (uint_eq_dec (app (nzhead d) d') Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply le_not_lt, Nat.le_0_l. }
+ clear m; set (m := match app _ _ with Nil => _ | _ => _ end).
+ intro Ha'.
+ replace m with (Neg (app (nzhead d) d')); [|now unfold m; revert Ha'; case app].
+ case (uint_eq_dec (nzhead d) Nil).
+ { intros->; simpl; intro H; exfalso; revert H; apply Nat.lt_irrefl. }
+ clear m; set (m := match nzhead _ with Nil => _ | _ => _ end).
+ intro Hd.
+ now replace m with (Neg (nzhead d)); [|unfold m; revert Hd; case nzhead].
+Qed.
+
+Lemma del_head_nb_digits d : del_head (nb_digits d) d = Nil.
+Proof.
+ apply to_list_inj.
+ rewrite nb_digits_spec, del_head_spec_small; [|now simpl].
+ now rewrite List.skipn_all.
+Qed.
+
+Lemma del_tail_nb_digits d : del_tail (nb_digits d) d = Nil.
+Proof. now unfold del_tail; rewrite <-nb_digits_rev, del_head_nb_digits. Qed.
+
+Lemma del_head_app n d d' :
+ n <= nb_digits d -> del_head n (app d d') = app (del_head n d) d'.
+Proof.
+ rewrite nb_digits_spec; intro Hn.
+ apply to_list_inj.
+ rewrite del_head_spec_small.
+ 2:{ now rewrite app_spec, List.app_length; apply le_plus_trans. }
+ rewrite !app_spec, (del_head_spec_small _ _ Hn).
+ rewrite List.skipn_app.
+ now rewrite (proj2 (Nat.sub_0_le _ _) Hn).
+Qed.
+
+Lemma del_tail_app n d d' :
+ n <= nb_digits d' -> del_tail n (app d d') = app d (del_tail n d').
+Proof.
+ rewrite nb_digits_spec; intro Hn.
+ unfold del_tail.
+ rewrite <-(of_list_to_list (rev (app d d'))), rev_spec, app_spec.
+ rewrite List.rev_app_distr, <-!rev_spec, <-app_spec, of_list_to_list.
+ rewrite del_head_app; [|now rewrite nb_digits_spec, rev_spec, List.rev_length].
+ apply to_list_inj.
+ rewrite rev_spec, !app_spec, !rev_spec.
+ now rewrite List.rev_app_distr, List.rev_involutive.
+Qed.
+
+Lemma del_tail_app_int n d d' :
+ n <= nb_digits d' -> del_tail_int n (app_int d d') = app_int d (del_tail n d').
+Proof. now case d as [d|d]; simpl; intro H; rewrite del_tail_app. Qed.
+
+Lemma app_del_tail_head n (d:uint) :
+ n <= nb_digits d -> app (del_tail n d) (del_head (nb_digits d - n) d) = d.
+Proof.
+ rewrite nb_digits_spec; intro Hn; unfold del_tail.
+ rewrite <-(of_list_to_list (app _ _)), app_spec, rev_spec.
+ rewrite del_head_spec_small; [|now rewrite rev_spec, List.rev_length].
+ rewrite del_head_spec_small; [|now apply Nat.le_sub_l].
+ rewrite rev_spec.
+ set (n' := _ - n).
+ assert (Hn' : n = length (to_list d) - n').
+ { now apply plus_minus; rewrite Nat.add_comm; symmetry; apply le_plus_minus_r. }
+ now rewrite Hn', <-List.firstn_skipn_rev, List.firstn_skipn, of_list_to_list.
+Qed.
+
+Lemma app_int_del_tail_head n (d:int) :
+ n <= nb_digits (abs d) ->
+ app_int (del_tail_int n d) (del_head (nb_digits (abs d) - n) (abs d)) = d.
+Proof. now case d; clear d; simpl; intros u Hu; rewrite app_del_tail_head. Qed.
+
+Lemma del_head_app_int_exact i f :
+ nb_digits f < nb_digits (unorm (app (abs i) f)) ->
+ del_head (nb_digits (unorm (app (abs i) f)) - nb_digits f) (unorm (app (abs i) f)) = f.
+Proof.
+ simpl; intro Hnb; generalize Hnb; rewrite (unorm_app_l _ _ Hnb); clear Hnb.
+ replace (_ - _) with (nb_digits (unorm (abs i))).
+ - now rewrite del_head_app; [rewrite del_head_nb_digits|].
+ - rewrite !nb_digits_spec, app_spec, List.app_length.
+ now rewrite Nat.add_comm, minus_plus.
+Qed.
+
+Lemma del_tail_app_int_exact i f :
+ nb_digits f < nb_digits (unorm (app (abs i) f)) ->
+ del_tail_int (nb_digits f) (norm (app_int i f)) = norm i.
+Proof.
+ simpl; intro Hnb.
+ rewrite (norm_app_int _ _ Hnb).
+ rewrite del_tail_app_int; [|now simpl].
+ now rewrite del_tail_nb_digits, app_int_nil_r.
Qed.
(** Normalization on little-endian numbers *)
@@ -193,6 +494,9 @@ Proof.
apply nzhead_revapp.
Qed.
+Lemma rev_rev d : rev (rev d) = d.
+Proof. now apply to_list_inj; rewrite !rev_spec, List.rev_involutive. Qed.
+
Lemma rev_nztail_rev d :
rev (nztail (rev d)) = nzhead d.
Proof.
@@ -247,47 +551,128 @@ Proof.
unfold unorm. now destruct nzhead.
Qed.
-Lemma unorm_D0 u : unorm (D0 u) = unorm u.
-Proof. reflexivity. Qed.
-
Lemma unorm_iter_D0 n u : unorm (Nat.iter n D0 u) = unorm u.
Proof. now induction n. Qed.
-Lemma nb_digits_unorm u :
- u <> Nil -> nb_digits (unorm u) <= nb_digits u.
+Lemma del_head_nonnil n u :
+ n < nb_digits u -> del_head n u <> Nil.
Proof.
- case u; clear u; [now simpl|intro u..]; [|now simpl..].
- intros _; unfold unorm.
- case_eq (nzhead (D0 u)); [|now intros u' <-; apply nb_digits_nzhead..].
- intros _; apply le_n_S, Nat.le_0_l.
+ now revert n; induction u; intro n;
+ [|case n; [|intro n'; simpl; intro H; apply IHu, lt_S_n]..].
Qed.
-Lemma nzhead_invol d : nzhead (nzhead d) = nzhead d.
+Lemma del_tail_nonnil n u :
+ n < nb_digits u -> del_tail n u <> Nil.
+Proof.
+ unfold del_tail.
+ rewrite <-nb_digits_rev.
+ generalize (rev u); clear u; intro u.
+ intros Hu H.
+ generalize (rev_nil_inv _ H); clear H.
+ now apply del_head_nonnil.
+Qed.
+
+Lemma nzhead_involutive d : nzhead (nzhead d) = nzhead d.
Proof.
now induction d.
Qed.
+#[deprecated(since="8.13",note="Use nzhead_involutive instead.")]
+Notation nzhead_invol := nzhead_involutive (only parsing).
-Lemma nztail_invol d : nztail (nztail d) = nztail d.
+Lemma nztail_involutive d : nztail (nztail d) = nztail d.
Proof.
rewrite <-(rev_rev (nztail _)), <-(rev_rev (nztail d)), <-(rev_rev d).
- now rewrite !rev_nztail_rev, nzhead_invol.
+ now rewrite !rev_nztail_rev, nzhead_involutive.
Qed.
+#[deprecated(since="8.13",note="Use nztail_involutive instead.")]
+Notation nztail_invol := nztail_involutive (only parsing).
-Lemma unorm_invol d : unorm (unorm d) = unorm d.
+Lemma unorm_involutive d : unorm (unorm d) = unorm d.
Proof.
unfold unorm.
destruct (nzhead d) eqn:E; trivial.
destruct (nzhead_nonzero _ _ E).
Qed.
+#[deprecated(since="8.13",note="Use unorm_involutive instead.")]
+Notation unorm_invol := unorm_involutive (only parsing).
-Lemma norm_invol d : norm (norm d) = norm d.
+Lemma norm_involutive d : norm (norm d) = norm d.
Proof.
unfold norm.
destruct d.
- - f_equal. apply unorm_invol.
+ - f_equal. apply unorm_involutive.
- destruct (nzhead d) eqn:E; auto.
destruct (nzhead_nonzero _ _ E).
Qed.
+#[deprecated(since="8.13",note="Use norm_involutive instead.")]
+Notation norm_invol := norm_involutive (only parsing).
+
+Lemma lnzhead_neq_d0_head l l' : ~(lnzhead l = cons d0 l').
+Proof. now induction l as [|h t Il]; [|case h]. Qed.
+
+Lemma lnzhead_head_nd0 h t : h <> d0 -> lnzhead (cons h t) = cons h t.
+Proof. now case h. Qed.
+
+Lemma nzhead_del_tail_nzhead_eq n u :
+ nzhead u = u ->
+ n < nb_digits u ->
+ nzhead (del_tail n u) = del_tail n u.
+Proof.
+ rewrite nb_digits_spec, <-List.rev_length.
+ intros Hu Hn.
+ apply to_list_inj; unfold del_tail.
+ rewrite nzhead_spec, rev_spec.
+ rewrite del_head_spec_small; [|now rewrite rev_spec; apply Nat.lt_le_incl].
+ rewrite rev_spec.
+ rewrite List.skipn_rev, List.rev_involutive.
+ generalize (f_equal to_list Hu) Hn; rewrite nzhead_spec; intro Hu'.
+ case (to_list u) as [|h t].
+ { simpl; intro H; exfalso; revert H; apply le_not_lt, Peano.le_0_n. }
+ intro Hn'; generalize (Nat.sub_gt _ _ Hn'); rewrite List.rev_length.
+ case (_ - _); [now simpl|]; intros n' _.
+ rewrite List.firstn_cons, lnzhead_head_nd0; [now simpl|].
+ intro Hh; revert Hu'; rewrite Hh; apply lnzhead_neq_d0_head.
+Qed.
+
+Lemma nzhead_del_tail_nzhead n u :
+ n < nb_digits (nzhead u) ->
+ nzhead (del_tail n (nzhead u)) = del_tail n (nzhead u).
+Proof. apply nzhead_del_tail_nzhead_eq, nzhead_involutive. Qed.
+
+Lemma unorm_del_tail_unorm n u :
+ n < nb_digits (unorm u) ->
+ unorm (del_tail n (unorm u)) = del_tail n (unorm u).
+Proof.
+ case (uint_eq_dec (nzhead u) Nil).
+ - unfold unorm; intros->; case n; [now simpl|]; intro n'.
+ now simpl; intro H; exfalso; generalize (lt_S_n _ _ H).
+ - unfold unorm.
+ set (m := match nzhead u with Nil => zero | _ => _ end).
+ intros H.
+ replace m with (nzhead u).
+ + intros H'.
+ rewrite (nzhead_del_tail_nzhead _ _ H').
+ now generalize (del_tail_nonnil _ _ H'); case del_tail.
+ + now unfold m; revert H; case nzhead.
+Qed.
+
+Lemma norm_del_tail_int_norm n d :
+ n < nb_digits (match norm d with Pos d | Neg d => d end) ->
+ norm (del_tail_int n (norm d)) = del_tail_int n (norm d).
+Proof.
+ case d; clear d; intros u; simpl.
+ - now intro H; simpl; rewrite unorm_del_tail_unorm.
+ - case (uint_eq_dec (nzhead u) Nil); intro Hu.
+ + now rewrite Hu; case n; [|intros n' Hn'; generalize (lt_S_n _ _ Hn')].
+ + set (m := match nzhead u with Nil => Pos zero | _ => _ end).
+ replace m with (Neg (nzhead u)); [|now unfold m; revert Hu; case nzhead].
+ unfold del_tail_int.
+ clear m Hu.
+ simpl.
+ intro H; generalize (del_tail_nonnil _ _ H).
+ rewrite (nzhead_del_tail_nzhead _ _ H).
+ now case del_tail.
+Qed.
Lemma nzhead_app_nzhead d d' :
nzhead (app (nzhead d) d') = nzhead (app d d').
@@ -299,7 +684,7 @@ Proof.
generalize (nzhead_revapp d d').
generalize (nzhead_revapp_0 (nztail d) d').
generalize (nzhead_revapp (nztail d) d').
- rewrite nztail_invol.
+ rewrite nztail_involutive.
now case nztail;
[intros _ H _ H'; rewrite (H eq_refl), (H' eq_refl)
|intros d'' H _ H' _; rewrite H; [rewrite H'|]..].
@@ -336,5 +721,5 @@ Proof.
|rewrite H'; unfold r; clear m r H'];
unfold norm;
rewrite rev_rev, <-Hd'';
- rewrite nzhead_revapp; rewrite nztail_invol; [|rewrite Hd'']..].
+ rewrite nzhead_revapp; rewrite nztail_involutive; [|rewrite Hd'']..].
Qed.
diff --git a/theories/Numbers/HexadecimalN.v b/theories/Numbers/HexadecimalN.v
index f333e2b7f6..93ba82d14a 100644
--- a/theories/Numbers/HexadecimalN.v
+++ b/theories/Numbers/HexadecimalN.v
@@ -74,7 +74,7 @@ Proof.
destruct (norm d) eqn:Hd; intros [= <-].
unfold N.to_hex_int. rewrite Unsigned.to_of. f_equal.
revert Hd; destruct d; simpl.
- - intros [= <-]. apply unorm_invol.
+ - intros [= <-]. apply unorm_involutive.
- destruct (nzhead d); now intros [= <-].
Qed.
@@ -93,7 +93,7 @@ Qed.
Lemma of_int_norm d : N.of_hex_int (norm d) = N.of_hex_int d.
Proof.
- unfold N.of_hex_int. now rewrite norm_invol.
+ unfold N.of_hex_int. now rewrite norm_involutive.
Qed.
Lemma of_inj_pos d d' :
diff --git a/theories/Numbers/HexadecimalNat.v b/theories/Numbers/HexadecimalNat.v
index b05184e821..94a14b90bd 100644
--- a/theories/Numbers/HexadecimalNat.v
+++ b/theories/Numbers/HexadecimalNat.v
@@ -289,7 +289,7 @@ Proof.
destruct (norm d) eqn:Hd; intros [= <-].
unfold Nat.to_hex_int. rewrite Unsigned.to_of. f_equal.
revert Hd; destruct d; simpl.
- - intros [= <-]. apply unorm_invol.
+ - intros [= <-]. apply unorm_involutive.
- destruct (nzhead d); now intros [= <-].
Qed.
@@ -308,7 +308,7 @@ Qed.
Lemma of_int_norm d : Nat.of_hex_int (norm d) = Nat.of_hex_int d.
Proof.
- unfold Nat.of_hex_int. now rewrite norm_invol.
+ unfold Nat.of_hex_int. now rewrite norm_involutive.
Qed.
Lemma of_inj_pos d d' :
diff --git a/theories/Numbers/HexadecimalQ.v b/theories/Numbers/HexadecimalQ.v
index 9bf43ceb88..a32019767c 100644
--- a/theories/Numbers/HexadecimalQ.v
+++ b/theories/Numbers/HexadecimalQ.v
@@ -16,442 +16,412 @@
Require Import Decimal DecimalFacts DecimalPos DecimalN DecimalZ.
Require Import Hexadecimal HexadecimalFacts HexadecimalPos HexadecimalN HexadecimalZ QArith.
-Lemma of_to (q:Q) : forall d, to_hexadecimal q = Some d -> of_hexadecimal d = q.
+Lemma of_IQmake_to_hexadecimal num den :
+ match IQmake_to_hexadecimal num den with
+ | None => True
+ | Some (HexadecimalExp _ _ _) => False
+ | Some (Hexadecimal i f) => of_hexadecimal (Hexadecimal i f) = IQmake (IZ_of_Z num) den
+ end.
+Proof.
+ unfold IQmake_to_hexadecimal.
+ generalize (Unsigned.nztail_to_hex_uint den).
+ case Hexadecimal.nztail; intros den' e_den'.
+ case den'; [now simpl|now simpl| |now simpl..]; clear den'; intro den'.
+ case den'; [ |now simpl..]; clear den'.
+ case e_den' as [|e_den']; simpl; intro H; injection H; clear H; intros->.
+ { now unfold of_hexadecimal; simpl; rewrite app_int_nil_r, HexadecimalZ.of_to. }
+ replace (16 ^ _)%positive with (Nat.iter (S e_den') (Pos.mul 16) 1%positive).
+ 2:{ induction e_den' as [|n IHn]; [now simpl| ].
+ now rewrite SuccNat2Pos.inj_succ, Pos.pow_succ_r, <-IHn. }
+ case Nat.ltb_spec; intro He_den'.
+ - unfold of_hexadecimal; simpl.
+ rewrite app_int_del_tail_head; [|now apply Nat.lt_le_incl].
+ rewrite HexadecimalZ.of_to.
+ now rewrite nb_digits_del_head_sub; [|now apply Nat.lt_le_incl].
+ - unfold of_hexadecimal; simpl.
+ rewrite nb_digits_iter_D0.
+ apply f_equal2.
+ + apply f_equal, HexadecimalZ.to_int_inj.
+ rewrite HexadecimalZ.to_of.
+ rewrite <-(HexadecimalZ.of_to num), HexadecimalZ.to_of.
+ case (Z.to_hex_int num); clear He_den' num; intro num; simpl.
+ * unfold app; simpl.
+ now rewrite unorm_D0, unorm_iter_D0, unorm_involutive.
+ * case (uint_eq_dec (nzhead num) Nil); [|intro Hn].
+ { intros->; simpl; unfold app; simpl.
+ now rewrite unorm_D0, unorm_iter_D0. }
+ replace (match nzhead num with Nil => _ | _ => _ end)
+ with (Neg (nzhead num)); [|now revert Hn; case nzhead].
+ simpl.
+ rewrite nzhead_iter_D0, nzhead_involutive.
+ now revert Hn; case nzhead.
+ + revert He_den'; case nb_digits as [|n]; [now simpl; rewrite Nat.add_0_r|].
+ intro Hn.
+ rewrite Nat.add_succ_r, Nat.add_comm.
+ now rewrite <-le_plus_minus; [|apply le_S_n].
+Qed.
+
+Lemma IZ_of_Z_IZ_to_Z z z' : IZ_to_Z z = Some z' -> IZ_of_Z z' = z.
+Proof. now case z as [| |p|p]; [|intro H; injection H; intros<-..]. Qed.
+
+Lemma of_IQmake_to_hexadecimal' num den :
+ match IQmake_to_hexadecimal' num den with
+ | None => True
+ | Some (HexadecimalExp _ _ _) => False
+ | Some (Hexadecimal i f) => of_hexadecimal (Hexadecimal i f) = IQmake num den
+ end.
+Proof.
+ unfold IQmake_to_hexadecimal'.
+ case_eq (IZ_to_Z num); [intros num' Hnum'|now simpl].
+ generalize (of_IQmake_to_hexadecimal num' den).
+ case IQmake_to_hexadecimal as [d|]; [|now simpl].
+ case d as [i f|]; [|now simpl].
+ now rewrite (IZ_of_Z_IZ_to_Z _ _ Hnum').
+Qed.
+
+Lemma of_to (q:IQ) : forall d, to_hexadecimal q = Some d -> of_hexadecimal d = q.
Proof.
- cut (match to_hexadecimal q with None => True | Some d => of_hexadecimal d = q end).
- { now case to_hexadecimal; [intros d <- d' Hd'; injection Hd'; intros ->|]. }
- destruct q as (num, den).
- unfold to_hexadecimal; simpl Qnum; simpl Qden.
- generalize (HexadecimalPos.Unsigned.nztail_to_hex_uint den).
- case Hexadecimal.nztail; intros u n.
- change 16%N with (2^4)%N; rewrite <-N.pow_mul_r.
- change 4%N with (N.of_nat 4); rewrite <-Nnat.Nat2N.inj_mul.
- change 4%Z with (Z.of_nat 4); rewrite <-Nat2Z.inj_mul.
- case u; clear u; try (intros; exact I); [| | |]; intro u;
- (case u; clear u; [|intros; exact I..]).
- - unfold Pos.of_hex_uint, Pos.of_hex_uint_acc; rewrite N.mul_1_l.
- case n.
- + unfold of_hexadecimal, app_int, app, Z.to_hex_int; simpl.
- intro H; inversion H as (H1); clear H H1.
- case num; [reflexivity|intro pnum; fold (rev (rev (Pos.to_hex_uint pnum)))..].
- * rewrite rev_rev; simpl.
- now unfold Z.of_hex_uint; rewrite HexadecimalPos.Unsigned.of_to.
- * rewrite rev_rev; simpl.
- now unfold Z.of_hex_uint; rewrite HexadecimalPos.Unsigned.of_to.
- + clear n; intros n.
- intro H; injection H; intros ->; clear H.
- unfold of_hexadecimal.
- rewrite DecimalZ.of_to.
- simpl nb_digits; rewrite Nat2Z.inj_0, Z.mul_0_r, Z.sub_0_r.
- now apply f_equal2; [rewrite app_int_nil_r, of_to|].
- - unfold Pos.of_hex_uint, Pos.of_hex_uint_acc.
- rewrite <-N.pow_succ_r', <-Nnat.Nat2N.inj_succ.
- intro H; injection H; intros ->; clear H.
- fold (4 * n)%nat.
- change 1%Z with (Z.of_nat 1); rewrite <-Znat.Nat2Z.inj_add.
- unfold of_hexadecimal.
- rewrite DecimalZ.of_to.
- simpl nb_digits; rewrite Nat2Z.inj_0, Z.mul_0_r, Z.sub_0_r.
- now apply f_equal2; [rewrite app_int_nil_r, of_to|].
- - change 2%Z with (Z.of_nat 2); rewrite <-Znat.Nat2Z.inj_add.
- unfold Pos.of_hex_uint, Pos.of_hex_uint_acc.
- change 4%N with (2^2)%N; rewrite <-N.pow_add_r.
- change 2%N with (N.of_nat 2); rewrite <-Nnat.Nat2N.inj_add.
- intro H; injection H; intros ->; clear H.
- fold (4 * n)%nat.
- unfold of_hexadecimal.
- rewrite DecimalZ.of_to.
- simpl nb_digits; rewrite Nat2Z.inj_0, Z.mul_0_r, Z.sub_0_r.
- now apply f_equal2; [rewrite app_int_nil_r, of_to|].
- - change 3%Z with (Z.of_nat 3); rewrite <-Znat.Nat2Z.inj_add.
- unfold Pos.of_hex_uint, Pos.of_hex_uint_acc.
- change 8%N with (2^3)%N; rewrite <-N.pow_add_r.
- change 3%N with (N.of_nat 3); rewrite <-Nnat.Nat2N.inj_add.
- intro H; injection H; intros ->; clear H.
- fold (4 * n)%nat.
- unfold of_hexadecimal.
- rewrite DecimalZ.of_to.
- simpl nb_digits; rewrite Nat2Z.inj_0, Z.mul_0_r, Z.sub_0_r.
- now apply f_equal2; [rewrite app_int_nil_r, of_to|].
+ intro d.
+ case q as [num den|q q'|q q']; simpl.
+ - generalize (of_IQmake_to_hexadecimal' num den).
+ case IQmake_to_hexadecimal' as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ now intros H H'; injection H'; clear H'; intros <-.
+ - case q as [num den| |]; [|now simpl..].
+ case q' as [num' den'| |]; [|now simpl..].
+ case num' as [z p| | |]; [|now simpl..].
+ case (Z.eq_dec z 2); [intros->|].
+ 2:{ case z; [now simpl| |now simpl]; intro pz'.
+ case pz'; [intros d0..| ]; [now simpl| |now simpl].
+ now case d0. }
+ case (Pos.eq_dec den' 1%positive); [intros->|now case den'].
+ generalize (of_IQmake_to_hexadecimal' num den).
+ case IQmake_to_hexadecimal' as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros <-; clear num den.
+ intros H; injection H; clear H; intros<-.
+ unfold of_hexadecimal; simpl.
+ now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+ - case q as [num den| |]; [|now simpl..].
+ case q' as [num' den'| |]; [|now simpl..].
+ case num' as [z p| | |]; [|now simpl..].
+ case (Z.eq_dec z 2); [intros->|].
+ 2:{ case z; [now simpl| |now simpl]; intro pz'.
+ case pz'; [intros d0..| ]; [now simpl| |now simpl].
+ now case d0. }
+ case (Pos.eq_dec den' 1%positive); [intros->|now case den'].
+ generalize (of_IQmake_to_hexadecimal' num den).
+ case IQmake_to_hexadecimal' as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros <-; clear num den.
+ intros H; injection H; clear H; intros<-.
+ unfold of_hexadecimal; simpl.
+ now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
Qed.
-(* normalize without fractional part, for instance norme 0x1.2p-1 is 0x12e-5 *)
-Definition hnorme (d:hexadecimal) : hexadecimal :=
- let '(i, f, e) :=
- match d with
- | Hexadecimal i f => (i, f, Decimal.Pos Decimal.Nil)
- | HexadecimalExp i f e => (i, f, e)
+
+Definition dnorm (d:hexadecimal) : hexadecimal :=
+ let norm_i i f :=
+ match i with
+ | Pos i => Pos (unorm i)
+ | Neg i => match nzhead (app i f) with Nil => Pos zero | _ => Neg (unorm i) end
end in
- let i := norm (app_int i f) in
- let e := (Z.of_int e - 4 * Z.of_nat (nb_digits f))%Z in
- match e with
- | Z0 => Hexadecimal i Nil
- | Zpos e => Hexadecimal (Pos.iter double i e) Nil
- | Zneg _ => HexadecimalExp i Nil (Decimal.norm (Z.to_int e))
+ match d with
+ | Hexadecimal i f => Hexadecimal (norm_i i f) f
+ | HexadecimalExp i f e =>
+ match Decimal.norm e with
+ | Decimal.Pos Decimal.zero => Hexadecimal (norm_i i f) f
+ | e => HexadecimalExp (norm_i i f) f e
+ end
end.
-Lemma hnorme_spec d :
- match hnorme d with
- | Hexadecimal i Nil => i = norm i
- | HexadecimalExp i Nil e =>
- i = norm i /\ e = Decimal.norm e /\ e <> Decimal.Pos Decimal.zero
- | _ => False
+Lemma dnorm_spec_i d :
+ let (i, f) :=
+ match d with Hexadecimal i f => (i, f) | HexadecimalExp i f _ => (i, f) end in
+ let i' := match dnorm d with Hexadecimal i _ => i | HexadecimalExp i _ _ => i end in
+ match i with
+ | Pos i => i' = Pos (unorm i)
+ | Neg i =>
+ (i' = Neg (unorm i) /\ (nzhead i <> Nil \/ nzhead f <> Nil))
+ \/ (i' = Pos zero /\ (nzhead i = Nil /\ nzhead f = Nil))
end.
Proof.
- case d; clear d; intros i f; [|intro e]; unfold hnorme; simpl.
- - case_eq (nb_digits f); [now simpl; rewrite norm_invol|]; intros nf Hnf.
- split; [now simpl; rewrite norm_invol|].
- unfold Z.of_nat.
- now rewrite <-!DecimalZ.to_of, !DecimalZ.of_to.
- - set (e' := (_ - _)%Z).
- case_eq e'; [|intro pe'..]; intro He'.
- + now rewrite norm_invol.
- + rewrite Pos2Nat.inj_iter.
- set (ne' := Pos.to_nat pe').
- fold (Nat.iter ne' double (norm (app_int i f))).
- induction ne'; [now simpl; rewrite norm_invol|].
- now rewrite Unsigned.nat_iter_S, <-double_norm, IHne', norm_invol.
- + split; [now rewrite norm_invol|].
- split; [now rewrite DecimalFacts.norm_invol|].
- rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- change (Decimal.Pos _) with (Z.to_int 0).
- now intro H; generalize (DecimalZ.to_int_inj _ _ H).
+ case d as [i f|i f e]; case i as [i|i].
+ - now simpl.
+ - simpl; case (uint_eq_dec (nzhead (app i f)) Nil); intro Ha.
+ + rewrite Ha; right; split; [now simpl|split].
+ * now unfold unorm; rewrite (nzhead_app_nil_l _ _ Ha).
+ * now unfold unorm; rewrite (nzhead_app_nil_r _ _ Ha).
+ + left; split; [now revert Ha; case nzhead|].
+ case (uint_eq_dec (nzhead i) Nil).
+ * intro Hi; right; intro Hf; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ * now intro H; left.
+ - simpl; case (Decimal.norm e); clear e; intro e; [|now simpl].
+ now case e; clear e; [|intro e..]; [|case e|..].
+ - simpl.
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ set (m' := match _ with Hexadecimal _ _ => _ | _ => _ end).
+ replace m' with m.
+ 2:{ unfold m'; case (Decimal.norm e); clear m' e; intro e; [|now simpl].
+ now case e; clear e; [|intro e..]; [|case e|..]. }
+ unfold m; case (uint_eq_dec (nzhead (app i f)) Nil); intro Ha.
+ + rewrite Ha; right; split; [now simpl|split].
+ * now unfold unorm; rewrite (nzhead_app_nil_l _ _ Ha).
+ * now unfold unorm; rewrite (nzhead_app_nil_r _ _ Ha).
+ + left; split; [now revert Ha; case nzhead|].
+ case (uint_eq_dec (nzhead i) Nil).
+ * intro Hi; right; intro Hf; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ * now intro H; left.
Qed.
-Lemma hnorme_invol d : hnorme (hnorme d) = hnorme d.
+Lemma dnorm_spec_f d :
+ let f := match d with Hexadecimal _ f => f | HexadecimalExp _ f _ => f end in
+ let f' := match dnorm d with Hexadecimal _ f => f | HexadecimalExp _ f _ => f end in
+ f' = f.
+Proof.
+ case d as [i f|i f e]; [now simpl|].
+ simpl; case (Decimal.int_eq_dec (Decimal.norm e) (Decimal.Pos Decimal.zero)); [now intros->|intro He].
+ set (i' := match i with Pos _ => _ | _ => _ end).
+ set (m := match Decimal.norm e with Decimal.Pos _ => _ | _ => _ end).
+ replace m with (HexadecimalExp i' f (Decimal.norm e)); [now simpl|].
+ unfold m; revert He; case (Decimal.norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..].
+Qed.
+
+Lemma dnorm_spec_e d :
+ match d, dnorm d with
+ | Hexadecimal _ _, Hexadecimal _ _ => True
+ | HexadecimalExp _ _ e, Hexadecimal _ _ =>
+ Decimal.norm e = Decimal.Pos Decimal.zero
+ | HexadecimalExp _ _ e, HexadecimalExp _ _ e' =>
+ e' = Decimal.norm e /\ e' <> Decimal.Pos Decimal.zero
+ | Hexadecimal _ _, HexadecimalExp _ _ _ => False
+ end.
Proof.
- case d; clear d; intros i f; [|intro e]; unfold hnorme; simpl.
- - case_eq (nb_digits f); [now simpl; rewrite app_int_nil_r, norm_invol|].
- intros nf Hnf.
- unfold Z.of_nat.
- simpl.
- set (pnf := Pos.to_uint _).
- set (nz := Decimal.nzhead pnf).
- assert (Hnz : nz <> Decimal.Nil).
- { unfold nz, pnf.
- rewrite <-DecimalFacts.unorm_0.
- rewrite <-DecimalPos.Unsigned.to_of.
- rewrite DecimalPos.Unsigned.of_to.
- change Decimal.zero with (N.to_uint 0).
- now intro H; generalize (DecimalN.Unsigned.to_uint_inj _ _ H). }
- set (m := match nz with Decimal.Nil => _ | _ => _ end).
- assert (Hm : m = (Decimal.Neg (Decimal.unorm pnf))).
- { now revert Hnz; unfold m, nz, Decimal.unorm; fold nz; case nz. }
- rewrite Hm; unfold pnf.
- rewrite <-DecimalPos.Unsigned.to_of, DecimalPos.Unsigned.of_to.
- simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
- rewrite Z.sub_0_r; simpl.
- fold pnf; fold nz; fold m; rewrite Hm; unfold pnf.
- rewrite <-DecimalPos.Unsigned.to_of, DecimalPos.Unsigned.of_to.
- now rewrite app_int_nil_r, norm_invol.
- - set (e' := (_ - _)%Z).
- case_eq e'; [|intro pe'..]; intro Hpe'.
- + now simpl; rewrite app_int_nil_r, norm_invol.
- + simpl; rewrite app_int_nil_r.
- apply f_equal2; [|reflexivity].
- rewrite Pos2Nat.inj_iter.
- set (ne' := Pos.to_nat pe').
- fold (Nat.iter ne' double (norm (app_int i f))).
- induction ne'; [now simpl; rewrite norm_invol|].
- now rewrite Unsigned.nat_iter_S, <-double_norm, IHne'.
- + rewrite <-DecimalZ.to_of, !DecimalZ.of_to; simpl.
- rewrite app_int_nil_r, norm_invol.
- set (pnf := Pos.to_uint _).
- set (nz := Decimal.nzhead pnf).
- assert (Hnz : nz <> Decimal.Nil).
- { unfold nz, pnf.
- rewrite <-DecimalFacts.unorm_0.
- rewrite <-DecimalPos.Unsigned.to_of.
- rewrite DecimalPos.Unsigned.of_to.
- change Decimal.zero with (N.to_uint 0).
- now intro H; generalize (DecimalN.Unsigned.to_uint_inj _ _ H). }
- set (m := match nz with Decimal.Nil => _ | _ => _ end).
- assert (Hm : m = (Decimal.Neg (Decimal.unorm pnf))).
- { now revert Hnz; unfold m, nz, Decimal.unorm; fold nz; case nz. }
- rewrite Hm; unfold pnf.
- now rewrite <-DecimalPos.Unsigned.to_of, DecimalPos.Unsigned.of_to.
+ case d as [i f|i f e]; [now simpl|].
+ simpl; case (Decimal.int_eq_dec (Decimal.norm e) (Decimal.Pos Decimal.zero)); [now intros->|intro He].
+ set (i' := match i with Pos _ => _ | _ => _ end).
+ set (m := match Decimal.norm e with Decimal.Pos _ => _ | _ => _ end).
+ replace m with (HexadecimalExp i' f (Decimal.norm e)); [now simpl|].
+ unfold m; revert He; case (Decimal.norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..].
Qed.
-Lemma to_of (d:hexadecimal) :
- to_hexadecimal (of_hexadecimal d) = Some (hnorme d).
+Lemma dnorm_involutive d : dnorm (dnorm d) = dnorm d.
Proof.
- unfold to_hexadecimal.
- pose (t10 := fun y => (y~0~0~0~0)%positive).
- assert (H : exists h e_den,
- Hexadecimal.nztail (Pos.to_hex_uint (Qden (of_hexadecimal d)))
- = (h, e_den)
- /\ (h = D1 Nil \/ h = D2 Nil \/ h = D4 Nil \/ h = D8 Nil)).
- { assert (H : forall p,
- Hexadecimal.nztail (Pos.to_hex_uint (Pos.iter (Pos.mul 2) 1%positive p))
- = ((match (Pos.to_nat p) mod 4 with 0%nat => D1 | 1 => D2 | 2 => D4 | _ => D8 end)%nat Nil,
- (Pos.to_nat p / 4)%nat)).
- { intro p; clear d; rewrite Pos2Nat.inj_iter.
- fold (Nat.iter (Pos.to_nat p) (Pos.mul 2) 1%positive).
- set (n := Pos.to_nat p).
- fold (Nat.iter n t10 1%positive).
- set (nm4 := (n mod 4)%nat); set (nd4 := (n / 4)%nat).
- rewrite (Nat.div_mod n 4); [|now simpl].
- unfold nm4, nd4; clear nm4 nd4.
- generalize (Nat.mod_upper_bound n 4 ltac:(now simpl)).
- generalize (n mod 4); generalize (n / 4)%nat.
- intros d r Hr; clear p n.
- induction d.
- { simpl; revert Hr.
- do 4 (case r; [now simpl|clear r; intro r]).
- intro H; exfalso.
- now do 4 (generalize (lt_S_n _ _ H); clear H; intro H). }
- rewrite Nat.mul_succ_r, <-Nat.add_assoc, (Nat.add_comm 4), Nat.add_assoc.
- rewrite (Nat.add_comm _ 4).
- change (4 + _)%nat with (S (S (S (S (4 * d + r))))).
- rewrite !Unsigned.nat_iter_S.
- rewrite !Pos.mul_assoc.
- unfold Pos.to_hex_uint.
- change (2 * 2 * 2 * 2)%positive with 0x10%positive.
- set (n := Nat.iter _ _ _).
- change (Pos.to_little_hex_uint _) with (Unsigned.to_lu (16 * N.pos n)).
- rewrite Unsigned.to_lhex_tenfold.
- unfold Hexadecimal.nztail; rewrite rev_rev.
- rewrite <-(rev_rev (Unsigned.to_lu _)).
- set (m := _ (rev _)).
- replace m with (let (r, n) := let (r, n) := m in (rev r, n) in (rev r, n)).
- 2:{ now case m; intros r' n'; rewrite rev_rev. }
- change (let (r, n) := m in (rev r, n))
- with (Hexadecimal.nztail (Pos.to_hex_uint n)).
- now unfold n; rewrite IHd, rev_rev; clear n m. }
- unfold of_hexadecimal.
- case d; intros i f; [|intro e]; unfold of_hexadecimal; simpl.
- - case (Z.of_nat _)%Z; [|intro p..];
- [now exists (D1 Nil), O; split; [|left]
- | |now exists (D1 Nil), O; split; [|left]].
- exists (D1 Nil), (Pos.to_nat p).
- split; [|now left]; simpl.
- change (Pos.iter _ _ _) with (Pos.iter (Pos.mul 2) 1%positive (4 * p)).
- rewrite H.
- rewrite Pos2Nat.inj_mul, Nat.mul_comm, Nat.div_mul; [|now simpl].
- now rewrite Nat.mod_mul; [|now simpl].
- - case (_ - _)%Z; [|intros p..]; [now exists (D1 Nil), O; split; [|left]..|].
- simpl Qden; rewrite H.
- eexists; eexists; split; [reflexivity|].
- case (_ mod _); [now left|intro n].
- case n; [now right; left|clear n; intro n].
- case n; [now right; right; left|clear n; intro n].
- now right; right; right. }
- generalize (HexadecimalPos.Unsigned.nztail_to_hex_uint (Qden (of_hexadecimal d))).
- destruct H as (h, (e, (He, Hh))); rewrite He; clear He.
- assert (Hn1 : forall p, N.pos (Pos.iter (Pos.mul 2) 1%positive p) = 1%N -> False).
- { intro p.
- rewrite Pos2Nat.inj_iter.
- case_eq (Pos.to_nat p); [|now simpl].
- intro H; exfalso; apply (lt_irrefl O).
- rewrite <-H at 2; apply Pos2Nat.is_pos. }
- assert (H16_2 : forall p, (16^p = 2^(4 * p))%positive).
- { intro p.
- apply (@f_equal _ _ (fun z => match z with Z.pos p => p | _ => 1%positive end)
- (Z.pos _) (Z.pos _)).
- rewrite !Pos2Z.inj_pow_pos, !Z.pow_pos_fold, Pos2Z.inj_mul.
- now change 16%Z with (2^4)%Z; rewrite <-Z.pow_mul_r. }
- assert (HN16_2 : forall n, (16^n = 2^(4 * n))%N).
- { intro n.
- apply N2Z.inj; rewrite !N2Z.inj_pow, N2Z.inj_mul.
- change (Z.of_N 16) with (2^4)%Z.
- now rewrite <-Z.pow_mul_r; [| |apply N2Z.is_nonneg]. }
- assert (Hn1' : forall p, N.pos (Pos.iter (Pos.mul 16) 1%positive p) = 1%N -> False).
- { intro p; fold (16^p)%positive; rewrite H16_2; apply Hn1. }
- assert (Ht10inj : forall n m, t10 n = t10 m -> n = m).
- { intros n m H; generalize (f_equal Z.pos H); clear H.
- change (Z.pos (t10 n)) with (Z.mul 0x10 (Z.pos n)).
- change (Z.pos (t10 m)) with (Z.mul 0x10 (Z.pos m)).
- rewrite Z.mul_comm, (Z.mul_comm 0x10).
- intro H; generalize (f_equal (fun z => Z.div z 0x10) H); clear H.
- now rewrite !Z.div_mul; [|now simpl..]; intro H; inversion H. }
- assert (Ht2inj : forall n m, Pos.mul 2 n = Pos.mul 2 m -> n = m).
- { intros n m H; generalize (f_equal Z.pos H); clear H.
- change (Z.pos (Pos.mul 2 n)) with (Z.mul 2 (Z.pos n)).
- change (Z.pos (Pos.mul 2 m)) with (Z.mul 2 (Z.pos m)).
- rewrite Z.mul_comm, (Z.mul_comm 2).
- intro H; generalize (f_equal (fun z => Z.div z 2) H); clear H.
- now rewrite !Z.div_mul; [|now simpl..]; intro H; inversion H. }
- assert (Hinj : forall n m,
- Nat.iter n (Pos.mul 2) 1%positive = Nat.iter m (Pos.mul 2) 1%positive
- -> n = m).
- { induction n; [now intro m; case m|].
- intro m; case m; [now simpl|]; clear m; intro m.
- rewrite !Unsigned.nat_iter_S.
- intro H; generalize (Ht2inj _ _ H); clear H; intro H.
- now rewrite (IHn _ H). }
- change 4%Z with (Z.of_nat 4); rewrite <-Nat2Z.inj_mul.
- change 1%Z with (Z.of_nat 1); rewrite <-Nat2Z.inj_add.
- change 2%Z with (Z.of_nat 2); rewrite <-Nat2Z.inj_add.
- change 3%Z with (Z.of_nat 3); rewrite <-Nat2Z.inj_add.
- destruct Hh as [Hh|[Hh|[Hh|Hh]]]; rewrite Hh; clear h Hh.
- - case e; clear e; [|intro e]; simpl; unfold of_hexadecimal, hnorme.
- + case d; clear d; intros i f; [|intro e].
- * generalize (nb_digits_pos f).
- case f;
- [|now clear f; intro f; intros H1 H2; exfalso; revert H1 H2;
- case nb_digits;
- [intros H _; apply (lt_irrefl O), H|intros n _; apply Hn1]..].
- now intros _ _; simpl; rewrite to_of.
- * rewrite <-DecimalZ.to_of, DecimalZ.of_to.
- set (emf := (_ - _)%Z).
- case_eq emf; [|intro pemf..].
- ++ now simpl; rewrite to_of.
- ++ intros Hemf _; simpl.
- apply f_equal, f_equal2; [|reflexivity].
- rewrite !Pos2Nat.inj_iter.
- fold (Nat.iter (Pos.to_nat pemf) (Z.mul 2) (Z.of_hex_int (app_int i f))).
- fold (Nat.iter (Pos.to_nat pemf) double (norm (app_int i f))).
- induction Pos.to_nat; [now simpl; rewrite HexadecimalZ.to_of|].
- now rewrite !Unsigned.nat_iter_S, <-IHn, double_to_hex_int.
- ++ simpl Qden; intros _ H; exfalso; revert H; apply Hn1.
- + case d; clear d; intros i f; [|intro e'].
- * simpl; case_eq (nb_digits f); [|intros nf' Hnf'];
- [now simpl; intros _ H; exfalso; symmetry in H; revert H; apply Hn1'|].
- unfold Z.of_nat, Z.opp, Qnum, Qden.
- rewrite H16_2.
- fold (Pos.mul 2); fold (2^(Pos.of_succ_nat nf')~0~0)%positive.
- intro H; injection H; clear H.
- unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intro H; injection H.
- clear H; intro H; generalize (SuccNat2Pos.inj _ _ H); clear H.
- intros <-.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite SuccNat2Pos.id_succ.
- change (_~0)%positive with (4 * Pos.of_succ_nat nf')%positive.
- now rewrite Pos2Nat.inj_mul, SuccNat2Pos.id_succ.
- * set (nemf := (_ - _)%Z); intro H.
- assert (H' : exists pnemf, nemf = Z.neg pnemf); [|revert H].
- { revert H; case nemf; [|intro pnemf..]; [..|now intros _; exists pnemf];
- simpl Qden; intro H; exfalso; symmetry in H; revert H; apply Hn1'. }
- destruct H' as (pnemf,Hpnemf); rewrite Hpnemf.
- unfold Qnum, Qden.
- rewrite H16_2.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H.
- intro H; revert Hpnemf; rewrite H; clear pnemf H; intro Hnemf.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite SuccNat2Pos.id_succ.
- change (_~0)%positive with (4 * Pos.of_succ_nat e)%positive.
- now rewrite Pos2Nat.inj_mul, SuccNat2Pos.id_succ.
- - simpl Pos.of_hex_uint.
- rewrite HN16_2.
- rewrite <-N.pow_succ_r; [|now apply N.le_0_l].
- rewrite <-N.succ_pos_spec.
- case d; clear d; intros i f; [|intro e']; unfold of_hexadecimal, hnorme.
- + set (em4f := (_ - _)%Z).
- case_eq em4f; [|intros pem4f..]; intro Hpem4f;
- [now simpl; intros H; exfalso; symmetry in H; revert H; apply Hn1..|].
- unfold Qnum, Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intros ->.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite SuccNat2Pos.id_succ.
- case e; [now simpl|intro e'']; simpl.
- unfold Pos.to_nat; simpl.
- now rewrite Pmult_nat_mult, SuccNat2Pos.id_succ, Nat.mul_comm.
- + set (em4f := (_ - _)%Z).
- case_eq em4f; [|intros pem4f..]; intro Hpem4f;
- [now simpl; intros H; exfalso; symmetry in H; revert H; apply Hn1..|].
- unfold Qnum, Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intros ->.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite SuccNat2Pos.id_succ.
- case e; [now simpl|intro e'']; simpl.
- unfold Pos.to_nat; simpl.
- now rewrite Pmult_nat_mult, SuccNat2Pos.id_succ, Nat.mul_comm.
- - simpl Pos.of_hex_uint.
- rewrite HN16_2.
- change 4%N with (2 * 2)%N at 1; rewrite <-!N.mul_assoc.
- do 2 (rewrite <-N.pow_succ_r; [|now apply N.le_0_l]).
- rewrite <-N.succ_pos_spec.
- case d; clear d; intros i f; [|intro e']; unfold of_hexadecimal, hnorme.
- + set (em4f := (_ - _)%Z).
- case_eq em4f; [|intros pem4f..]; intro Hpem4f;
- [now simpl; intros H; exfalso; symmetry in H; revert H; apply Hn1..|].
- unfold Qnum, Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intros ->.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite <-SuccNat2Pos.inj_succ.
- rewrite SuccNat2Pos.id_succ.
- case e; [now simpl|intro e'']; simpl.
- unfold Pos.to_nat; simpl.
- now rewrite Pmult_nat_mult, SuccNat2Pos.id_succ, Nat.mul_comm.
- + set (em4f := (_ - _)%Z).
- case_eq em4f; [|intros pem4f..]; intro Hpem4f;
- [now simpl; intros H; exfalso; symmetry in H; revert H; apply Hn1..|].
- unfold Qnum, Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intros ->.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite <-SuccNat2Pos.inj_succ.
- rewrite SuccNat2Pos.id_succ.
- case e; [now simpl|intro e'']; simpl.
- unfold Pos.to_nat; simpl.
- now rewrite Pmult_nat_mult, SuccNat2Pos.id_succ, Nat.mul_comm.
- - simpl Pos.of_hex_uint.
- rewrite HN16_2.
- change 8%N with (2 * 2 * 2)%N; rewrite <-!N.mul_assoc.
- do 3 (rewrite <-N.pow_succ_r; [|now apply N.le_0_l]).
- rewrite <-N.succ_pos_spec.
- case d; clear d; intros i f; [|intro e']; unfold of_hexadecimal, hnorme.
- + set (em4f := (_ - _)%Z).
- case_eq em4f; [|intros pem4f..]; intro Hpem4f;
- [now simpl; intros H; exfalso; symmetry in H; revert H; apply Hn1..|].
- unfold Qnum, Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intros ->.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite <-!SuccNat2Pos.inj_succ.
- rewrite SuccNat2Pos.id_succ.
- case e; [now simpl|intro e'']; simpl.
- unfold Pos.to_nat; simpl.
- now rewrite Pmult_nat_mult, SuccNat2Pos.id_succ, Nat.mul_comm.
- + set (em4f := (_ - _)%Z).
- case_eq em4f; [|intros pem4f..]; intro Hpem4f;
- [now simpl; intros H; exfalso; symmetry in H; revert H; apply Hn1..|].
- unfold Qnum, Qden.
- intro H; injection H; clear H; unfold Pos.pow; rewrite !Pos2Nat.inj_iter.
- intro H; generalize (Hinj _ _ H); clear H; intro H.
- generalize (Pos2Nat.inj _ _ H); clear H; intros ->.
- rewrite to_of.
- rewrite <-DecimalZ.to_of, DecimalZ.of_to; simpl.
- do 4 apply f_equal.
- apply Pos2Nat.inj.
- rewrite <-!SuccNat2Pos.inj_succ.
- rewrite SuccNat2Pos.id_succ.
- case e; [now simpl|intro e'']; simpl.
- unfold Pos.to_nat; simpl.
- now rewrite Pmult_nat_mult, SuccNat2Pos.id_succ, Nat.mul_comm.
+ case d as [i f|i f e]; case i as [i|i].
+ - now simpl; rewrite unorm_involutive.
+ - simpl; case (uint_eq_dec (nzhead (app i f)) Nil); [now intros->|intro Ha].
+ set (m := match nzhead _ with Nil =>_ | _ => _ end).
+ replace m with (Neg (unorm i)).
+ 2:{ now unfold m; revert Ha; case nzhead. }
+ case (uint_eq_dec (nzhead i) Nil); intro Hi.
+ + unfold unorm; rewrite Hi; simpl.
+ case (uint_eq_dec (nzhead f) Nil).
+ * intro Hf; exfalso; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ * now case nzhead.
+ + rewrite unorm_involutive, (unorm_nzhead _ Hi), nzhead_app_nzhead.
+ now revert Ha; case nzhead.
+ - simpl; case (Decimal.int_eq_dec (Decimal.norm e) (Decimal.Pos Decimal.zero)); intro He.
+ + now rewrite He; simpl; rewrite unorm_involutive.
+ + set (m := match Decimal.norm e with Decimal.Pos _ => _ | _ => _ end).
+ replace m with (HexadecimalExp (Pos (unorm i)) f (Decimal.norm e)).
+ 2:{ unfold m; revert He; case (Decimal.norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..]. }
+ simpl; rewrite DecimalFacts.norm_involutive, unorm_involutive.
+ revert He; case (Decimal.norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..].
+ - simpl; case (Decimal.int_eq_dec (Decimal.norm e) (Decimal.Pos Decimal.zero)); intro He.
+ + rewrite He; simpl.
+ case (uint_eq_dec (nzhead (app i f)) Nil); [now intros->|intro Ha].
+ set (m := match nzhead _ with Nil =>_ | _ => _ end).
+ replace m with (Neg (unorm i)).
+ 2:{ now unfold m; revert Ha; case nzhead. }
+ case (uint_eq_dec (nzhead i) Nil); intro Hi.
+ * unfold unorm; rewrite Hi; simpl.
+ case (uint_eq_dec (nzhead f) Nil).
+ -- intro Hf; exfalso; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ -- now case nzhead.
+ * rewrite unorm_involutive, (unorm_nzhead _ Hi), nzhead_app_nzhead.
+ now revert Ha; case nzhead.
+ + set (m := match Decimal.norm e with Decimal.Pos _ => _ | _ => _ end).
+ pose (i' := match nzhead (app i f) with Nil => Pos zero | _ => Neg (unorm i) end).
+ replace m with (HexadecimalExp i' f (Decimal.norm e)).
+ 2:{ unfold m; revert He; case (Decimal.norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..]. }
+ simpl; rewrite DecimalFacts.norm_involutive.
+ set (i'' := match i' with Pos _ => _ | _ => _ end).
+ clear m; set (m := match Decimal.norm e with Decimal.Pos _ => _ | _ => _ end).
+ replace m with (HexadecimalExp i'' f (Decimal.norm e)).
+ 2:{ unfold m; revert He; case (Decimal.norm e); clear m e; intro e; [|now simpl].
+ now case e; clear e; [|intro e; case e|..]. }
+ unfold i'', i'.
+ case (uint_eq_dec (nzhead (app i f)) Nil); [now intros->|intro Ha].
+ fold i'; replace i' with (Neg (unorm i)).
+ 2:{ now unfold i'; revert Ha; case nzhead. }
+ case (uint_eq_dec (nzhead i) Nil); intro Hi.
+ * unfold unorm; rewrite Hi; simpl.
+ case (uint_eq_dec (nzhead f) Nil).
+ -- intro Hf; exfalso; apply Ha.
+ now rewrite <-nzhead_app_nzhead, Hi, app_nil_l.
+ -- now case nzhead.
+ * rewrite unorm_involutive, (unorm_nzhead _ Hi), nzhead_app_nzhead.
+ now revert Ha; case nzhead.
+Qed.
+
+Lemma IZ_to_Z_IZ_of_Z z : IZ_to_Z (IZ_of_Z z) = Some z.
+Proof. now case z. Qed.
+
+Lemma dnorm_i_exact i f :
+ (nb_digits f < nb_digits (unorm (app (abs i) f)))%nat ->
+ match i with
+ | Pos i => Pos (unorm i)
+ | Neg i =>
+ match nzhead (app i f) with
+ | Nil => Pos zero
+ | _ => Neg (unorm i)
+ end
+ end = norm i.
+Proof.
+ case i as [ni|ni]; [now simpl|]; simpl.
+ case (uint_eq_dec (nzhead (app ni f)) Nil); intro Ha.
+ { now rewrite Ha, (nzhead_app_nil_l _ _ Ha). }
+ rewrite (unorm_nzhead _ Ha).
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (Neg (unorm ni)); [|now unfold m; revert Ha; case nzhead].
+ case (uint_eq_dec (nzhead ni) Nil); intro Hni.
+ { rewrite <-nzhead_app_nzhead, Hni, app_nil_l.
+ intro H; exfalso; revert H; apply le_not_lt, nb_digits_nzhead. }
+ clear m; set (m := match nzhead ni with Nil => _ | _ => _ end).
+ replace m with (Neg (nzhead ni)); [|now unfold m; revert Hni; case nzhead].
+ now rewrite (unorm_nzhead _ Hni).
+Qed.
+
+Lemma dnorm_i_exact' i f :
+ (nb_digits (unorm (app (abs i) f)) <= nb_digits f)%nat ->
+ match i with
+ | Pos i => Pos (unorm i)
+ | Neg i =>
+ match nzhead (app i f) with
+ | Nil => Pos zero
+ | _ => Neg (unorm i)
+ end
+ end =
+ match norm (app_int i f) with
+ | Pos _ => Pos zero
+ | Neg _ => Neg zero
+ end.
+Proof.
+ case i as [ni|ni]; simpl.
+ { now intro Hnb; rewrite (unorm_app_zero _ _ Hnb). }
+ unfold unorm.
+ case (uint_eq_dec (nzhead (app ni f)) Nil); intro Hn.
+ { now rewrite Hn. }
+ set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (nzhead (app ni f)).
+ 2:{ now unfold m; revert Hn; case nzhead. }
+ clear m; set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (Neg (unorm ni)).
+ 2:{ now unfold m, unorm; revert Hn; case nzhead. }
+ clear m; set (m := match nzhead _ with Nil => _ | _ => _ end).
+ replace m with (Neg (nzhead (app ni f))).
+ 2:{ now unfold m; revert Hn; case nzhead. }
+ rewrite <-(unorm_nzhead _ Hn).
+ now intro H; rewrite (unorm_app_zero _ _ H).
+Qed.
+
+Lemma to_of (d:hexadecimal) : to_hexadecimal (of_hexadecimal d) = Some (dnorm d).
+Proof.
+ case d as [i f|i f e].
+ - unfold of_hexadecimal; simpl; unfold IQmake_to_hexadecimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_hexadecimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 16).
+ rewrite nztail_to_hex_uint_pow16, to_of.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ + rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ + rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ * rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ * rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
+ - unfold of_hexadecimal; simpl.
+ rewrite <-DecimalZ.to_of.
+ case (Z.of_int e); clear e; [|intro e..]; simpl.
+ + unfold IQmake_to_hexadecimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_hexadecimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 16).
+ rewrite nztail_to_hex_uint_pow16, to_of.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ * rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ * rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ -- rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ -- rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
+ + unfold IQmake_to_hexadecimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_hexadecimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 16).
+ rewrite nztail_to_hex_uint_pow16, to_of.
+ generalize (DecimalPos.Unsigned.to_uint_nonzero e); intro He.
+ set (dnorm_i := match i with Pos _ => _ | _ => _ end).
+ set (m := match Pos.to_uint e with Decimal.Nil => _ | _ => _ end).
+ replace m with (HexadecimalExp dnorm_i f (Decimal.Pos (Pos.to_uint e))).
+ 2:{ now unfold m; revert He; case (Pos.to_uint e); [|intro u; case u|..]. }
+ clear m; unfold dnorm_i.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ * rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ * rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ -- rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ -- rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
+ + unfold IQmake_to_hexadecimal'.
+ rewrite IZ_to_Z_IZ_of_Z.
+ unfold IQmake_to_hexadecimal; simpl.
+ change (fun _ : positive => _) with (Pos.mul 16).
+ rewrite nztail_to_hex_uint_pow16, to_of.
+ case_eq (nb_digits f); [|intro nb]; intro Hnb.
+ * rewrite (nb_digits_0 _ Hnb), app_int_nil_r.
+ case i as [ni|ni]; [now simpl|].
+ rewrite app_nil_r; simpl; unfold unorm.
+ now case (nzhead ni).
+ * rewrite <-Hnb.
+ rewrite abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnb'.
+ -- rewrite (del_tail_app_int_exact _ _ Hnb').
+ rewrite (del_head_app_int_exact _ _ Hnb').
+ now rewrite (dnorm_i_exact _ _ Hnb').
+ -- rewrite (unorm_app_r _ _ Hnb').
+ rewrite iter_D0_unorm; [|now apply nb_digits_n0; rewrite Hnb].
+ now rewrite dnorm_i_exact'.
Qed.
(** Some consequences *)
@@ -466,68 +436,24 @@ Proof.
now intros d _ H1 H2; rewrite <-(H1 d eq_refl), <-(H2 d eq_refl).
Qed.
-Lemma to_hexadecimal_surj d : exists q, to_hexadecimal q = Some (hnorme d).
+Lemma to_hexadecimal_surj d : exists q, to_hexadecimal q = Some (dnorm d).
Proof.
exists (of_hexadecimal d). apply to_of.
Qed.
-Lemma of_hexadecimal_hnorme d : of_hexadecimal (hnorme d) = of_hexadecimal d.
-Proof.
- unfold of_hexadecimal, hnorme.
- destruct d.
- - simpl Z.of_int; unfold Z.of_uint, Z.of_N, Pos.of_uint.
- rewrite Z.sub_0_l.
- set (n4f := (- _)%Z).
- case_eq n4f; [|intro pn4f..]; intro Hn4f.
- + apply f_equal2; [|reflexivity].
- rewrite app_int_nil_r.
- now rewrite <-HexadecimalZ.to_of, HexadecimalZ.of_to.
- + apply f_equal2; [|reflexivity].
- rewrite app_int_nil_r.
- generalize (app_int i f); intro i'.
- rewrite !Pos2Nat.inj_iter.
- generalize (Pos.to_nat pn4f); intro n.
- fold (Nat.iter n double (norm i')).
- fold (Nat.iter n (Z.mul 2) (Z.of_hex_int i')).
- induction n; [now simpl; rewrite <-HexadecimalZ.to_of, HexadecimalZ.of_to|].
- now rewrite !Unsigned.nat_iter_S, <-IHn, of_hex_int_double.
- + unfold nb_digits, Z.of_nat.
- rewrite Z.mul_0_r, Z.sub_0_r.
- rewrite <-DecimalZ.to_of, !DecimalZ.of_to.
- rewrite app_int_nil_r.
- now rewrite <-HexadecimalZ.to_of, HexadecimalZ.of_to.
- - set (nem4f := (_ - _)%Z).
- case_eq nem4f; [|intro pnem4f..]; intro Hnem4f.
- + apply f_equal2; [|reflexivity].
- rewrite app_int_nil_r.
- now rewrite <-HexadecimalZ.to_of, HexadecimalZ.of_to.
- + apply f_equal2; [|reflexivity].
- rewrite app_int_nil_r.
- generalize (app_int i f); intro i'.
- rewrite !Pos2Nat.inj_iter.
- generalize (Pos.to_nat pnem4f); intro n.
- fold (Nat.iter n double (norm i')).
- fold (Nat.iter n (Z.mul 2) (Z.of_hex_int i')).
- induction n; [now simpl; rewrite <-HexadecimalZ.to_of, HexadecimalZ.of_to|].
- now rewrite !Unsigned.nat_iter_S, <-IHn, of_hex_int_double.
- + unfold nb_digits, Z.of_nat.
- rewrite Z.mul_0_r, Z.sub_0_r.
- rewrite <-DecimalZ.to_of, !DecimalZ.of_to.
- rewrite app_int_nil_r.
- now rewrite <-HexadecimalZ.to_of, HexadecimalZ.of_to.
-Qed.
+Lemma of_hexadecimal_dnorm d : of_hexadecimal (dnorm d) = of_hexadecimal d.
+Proof. now apply to_hexadecimal_inj; rewrite !to_of; [|rewrite dnorm_involutive]. Qed.
-Lemma of_inj d d' :
- of_hexadecimal d = of_hexadecimal d' -> hnorme d = hnorme d'.
+Lemma of_inj d d' : of_hexadecimal d = of_hexadecimal d' -> dnorm d = dnorm d'.
Proof.
- intros.
- cut (Some (hnorme d) = Some (hnorme d')); [now intro H'; injection H'|].
- rewrite <- !to_of. now f_equal.
+ intro H.
+ apply (@f_equal _ _ (fun x => match x with Some x => x | _ => d end)
+ (Some (dnorm d)) (Some (dnorm d'))).
+ now rewrite <- !to_of, H.
Qed.
-Lemma of_iff d d' :
- of_hexadecimal d = of_hexadecimal d' <-> hnorme d = hnorme d'.
+Lemma of_iff d d' : of_hexadecimal d = of_hexadecimal d' <-> dnorm d = dnorm d'.
Proof.
- split. apply of_inj. intros E. rewrite <- of_hexadecimal_hnorme, E.
- apply of_hexadecimal_hnorme.
+ split. apply of_inj. intros E. rewrite <- of_hexadecimal_dnorm, E.
+ apply of_hexadecimal_dnorm.
Qed.
diff --git a/theories/Numbers/HexadecimalR.v b/theories/Numbers/HexadecimalR.v
new file mode 100644
index 0000000000..2deecc5847
--- /dev/null
+++ b/theories/Numbers/HexadecimalR.v
@@ -0,0 +1,302 @@
+(************************************************************************)
+(* * 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) *)
+(************************************************************************)
+
+(** * HexadecimalR
+
+ Proofs that conversions between hexadecimal numbers and [R]
+ are bijections. *)
+
+Require Import Decimal DecimalFacts.
+Require Import Hexadecimal HexadecimalFacts HexadecimalPos HexadecimalZ.
+Require Import HexadecimalQ Rdefinitions.
+
+Lemma of_IQmake_to_hexadecimal num den :
+ match IQmake_to_hexadecimal num den with
+ | None => True
+ | Some (HexadecimalExp _ _ _) => False
+ | Some (Hexadecimal i f) =>
+ of_hexadecimal (Hexadecimal i f) = IRQ (QArith_base.Qmake num den)
+ end.
+Proof.
+ unfold IQmake_to_hexadecimal.
+ case (Pos.eq_dec den 1); [now intros->|intro Hden].
+ assert (Hf : match QArith_base.IQmake_to_hexadecimal num den with
+ | Some (Hexadecimal i f) => f <> Nil
+ | _ => True
+ end).
+ { unfold QArith_base.IQmake_to_hexadecimal; simpl.
+ generalize (Unsigned.nztail_to_hex_uint den).
+ case Hexadecimal.nztail as [den' e_den'].
+ case den'; [now simpl|now simpl| |now simpl..]; clear den'; intro den'.
+ case den'; [ |now simpl..]; clear den'.
+ case e_den' as [|e_den']; [now simpl; intros H _; apply Hden; injection H|].
+ intros _.
+ case Nat.ltb_spec; intro He_den'.
+ - apply del_head_nonnil.
+ revert He_den'; case nb_digits as [|n]; [now simpl|].
+ now intro H; simpl; apply le_lt_n_Sm, Nat.le_sub_l.
+ - apply nb_digits_n0.
+ now rewrite nb_digits_iter_D0, Nat.sub_add. }
+ replace (match den with 1%positive => _ | _ => _ end)
+ with (QArith_base.IQmake_to_hexadecimal num den); [|now revert Hden; case den].
+ generalize (of_IQmake_to_hexadecimal num den).
+ case QArith_base.IQmake_to_hexadecimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ unfold of_hexadecimal; simpl.
+ intro H; injection H; clear H; intros <-.
+ intro H; generalize (f_equal QArith_base.IZ_to_Z H); clear H.
+ rewrite !IZ_to_Z_IZ_of_Z; intro H; injection H; clear H; intros<-.
+ now revert Hf; case f.
+Qed.
+
+Lemma of_to (q:IR) : forall d, to_hexadecimal q = Some d -> of_hexadecimal d = q.
+Proof.
+ intro d.
+ case q as [z|q|r r'|r r']; simpl.
+ - case z as [z p| |p|p].
+ + now simpl.
+ + now simpl; intro H; injection H; clear H; intros<-.
+ + simpl; intro H; injection H; clear H; intros<-.
+ now unfold of_hexadecimal; simpl; unfold Z.of_hex_uint; rewrite Unsigned.of_to.
+ + simpl; intro H; injection H; clear H; intros<-.
+ now unfold of_hexadecimal; simpl; unfold Z.of_hex_uint; rewrite Unsigned.of_to.
+ - case q as [num den].
+ generalize (of_IQmake_to_hexadecimal num den).
+ case IQmake_to_hexadecimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ now intros H H'; injection H'; intros<-.
+ - case r as [z|q| |]; [|case q as[num den]|now simpl..];
+ (case r' as [z'| | |]; [|now simpl..]);
+ (case z' as [p e| | |]; [|now simpl..]).
+ + case (Z.eq_dec p 2); [intros->|intro Hp].
+ 2:{ now revert Hp; case p;
+ [|intro d0; case d0; [intro d1..|]; [|case d1|]..]. }
+ case z as [| |p|p]; [now simpl|..]; intro H; injection H; intros<-.
+ * now unfold of_hexadecimal; simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
+ * unfold of_hexadecimal; simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+ now unfold Z.of_hex_uint; rewrite Unsigned.of_to.
+ * unfold of_hexadecimal; simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+ now unfold Z.of_hex_uint; rewrite Unsigned.of_to.
+ + case (Z.eq_dec p 2); [intros->|intro Hp].
+ 2:{ now revert Hp; case p;
+ [|intro d0; case d0; [intro d1..|]; [|case d1|]..]. }
+ generalize (of_IQmake_to_hexadecimal num den).
+ case IQmake_to_hexadecimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros H H'; injection H'; clear H'; intros<-.
+ unfold of_hexadecimal; simpl.
+ change (match f with Nil => _ | _ => _ end) with (of_hexadecimal (Hexadecimal i f)).
+ rewrite H; clear H.
+ now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
+ - case r as [z|q| |]; [|case q as[num den]|now simpl..];
+ (case r' as [z'| | |]; [|now simpl..]);
+ (case z' as [p e| | |]; [|now simpl..]).
+ + case (Z.eq_dec p 2); [intros->|intro Hp].
+ 2:{ now revert Hp; case p;
+ [|intro d0; case d0; [intro d1..|]; [|case d1|]..]. }
+ case z as [| |p|p]; [now simpl|..]; intro H; injection H; intros<-.
+ * now unfold of_hexadecimal; simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
+ * unfold of_hexadecimal; simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+ now unfold Z.of_hex_uint; rewrite Unsigned.of_to.
+ * unfold of_hexadecimal; simpl; unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to; simpl.
+ now unfold Z.of_hex_uint; rewrite Unsigned.of_to.
+ + case (Z.eq_dec p 2); [intros->|intro Hp].
+ 2:{ now revert Hp; case p;
+ [|intro d0; case d0; [intro d1..|]; [|case d1|]..]. }
+ generalize (of_IQmake_to_hexadecimal num den).
+ case IQmake_to_hexadecimal as [d'|]; [|now simpl].
+ case d' as [i f|]; [|now simpl].
+ intros H H'; injection H'; clear H'; intros<-.
+ unfold of_hexadecimal; simpl.
+ change (match f with Nil => _ | _ => _ end) with (of_hexadecimal (Hexadecimal i f)).
+ rewrite H; clear H.
+ now unfold Z.of_uint; rewrite DecimalPos.Unsigned.of_to.
+Qed.
+
+Lemma to_of (d:hexadecimal) : to_hexadecimal (of_hexadecimal d) = Some (dnorm d).
+Proof.
+ case d as [i f|i f e].
+ - unfold of_hexadecimal; simpl.
+ case (uint_eq_dec f Nil); intro Hf.
+ + rewrite Hf; clear f Hf.
+ unfold to_hexadecimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, HexadecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ + set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_hexadecimal; simpl.
+ unfold IQmake_to_hexadecimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_hexadecimal (Z.of_hex_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_hexadecimal, n; simpl.
+ rewrite nztail_to_hex_uint_pow16.
+ clear r; set (r := if _ <? _ then Some (Hexadecimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite HexadecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ * rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ * rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+ - unfold of_hexadecimal; simpl.
+ rewrite <-(DecimalZ.to_of e).
+ case (Z.of_int e); clear e; [|intro e..]; simpl.
+ + case (uint_eq_dec f Nil); intro Hf.
+ * rewrite Hf; clear f Hf.
+ unfold to_hexadecimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, HexadecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ * set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_hexadecimal; simpl.
+ unfold IQmake_to_hexadecimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_hexadecimal (Z.of_hex_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_hexadecimal, n; simpl.
+ rewrite nztail_to_hex_uint_pow16.
+ clear r; set (r := if _ <? _ then Some (Hexadecimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite HexadecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ -- rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ -- rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+ + set (i' := match i with Pos _ => _ | _ => _ end).
+ set (m := match Pos.to_uint e with Decimal.Nil => _ | _ => _ end).
+ replace m with (HexadecimalExp i' f (Decimal.Pos (Pos.to_uint e))).
+ 2:{ unfold m; generalize (DecimalPos.Unsigned.to_uint_nonzero e).
+ now case Pos.to_uint; [|intro u; case u|..]. }
+ unfold i'; clear i' m.
+ case (uint_eq_dec f Nil); intro Hf.
+ * rewrite Hf; clear f Hf.
+ unfold to_hexadecimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, HexadecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ * set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_hexadecimal; simpl.
+ unfold IQmake_to_hexadecimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_hexadecimal (Z.of_hex_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_hexadecimal, n; simpl.
+ rewrite nztail_to_hex_uint_pow16.
+ clear r; set (r := if _ <? _ then Some (Hexadecimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite HexadecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ -- rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ -- rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+ + case (uint_eq_dec f Nil); intro Hf.
+ * rewrite Hf; clear f Hf.
+ unfold to_hexadecimal; simpl.
+ rewrite IZ_to_Z_IZ_of_Z, HexadecimalZ.to_of.
+ case i as [i|i]; [now simpl|]; simpl.
+ rewrite app_nil_r.
+ case (uint_eq_dec (nzhead i) Nil); [now intros->|intro Hi].
+ now rewrite (unorm_nzhead _ Hi); revert Hi; case nzhead.
+ * set (r := IRQ _).
+ set (m := match f with Nil => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ unfold to_hexadecimal; simpl.
+ unfold IQmake_to_hexadecimal; simpl.
+ set (n := Nat.iter _ _ _).
+ case (Pos.eq_dec n 1); intro Hn.
+ exfalso; apply Hf.
+ { now apply nb_digits_0; revert Hn; unfold n; case nb_digits. }
+ clear m; set (m := match n with 1%positive | _ => _ end).
+ replace m with (QArith_base.IQmake_to_hexadecimal (Z.of_hex_int (app_int i f)) n).
+ 2:{ now unfold m; revert Hn; case n. }
+ unfold QArith_base.IQmake_to_hexadecimal, n; simpl.
+ rewrite nztail_to_hex_uint_pow16.
+ clear r; set (r := if _ <? _ then Some (Hexadecimal _ _) else Some _).
+ clear m; set (m := match nb_digits f with 0 => _ | _ => _ end).
+ replace m with r; [unfold r|now unfold m; revert Hf; case f].
+ rewrite HexadecimalZ.to_of, abs_norm, abs_app_int.
+ case Nat.ltb_spec; intro Hnf.
+ -- rewrite (del_tail_app_int_exact _ _ Hnf).
+ rewrite (del_head_app_int_exact _ _ Hnf).
+ now rewrite (dnorm_i_exact _ _ Hnf).
+ -- rewrite (unorm_app_r _ _ Hnf).
+ rewrite (iter_D0_unorm _ Hf).
+ now rewrite dnorm_i_exact'.
+Qed.
+
+(** Some consequences *)
+
+Lemma to_hexadecimal_inj q q' :
+ to_hexadecimal q <> None -> to_hexadecimal q = to_hexadecimal q' -> q = q'.
+Proof.
+ intros Hnone EQ.
+ generalize (of_to q) (of_to q').
+ rewrite <-EQ.
+ revert Hnone; case to_hexadecimal; [|now simpl].
+ now intros d _ H1 H2; rewrite <-(H1 d eq_refl), <-(H2 d eq_refl).
+Qed.
+
+Lemma to_hexadecimal_surj d : exists q, to_hexadecimal q = Some (dnorm d).
+Proof.
+ exists (of_hexadecimal d). apply to_of.
+Qed.
+
+Lemma of_hexadecimal_dnorm d : of_hexadecimal (dnorm d) = of_hexadecimal d.
+Proof. now apply to_hexadecimal_inj; rewrite !to_of; [|rewrite dnorm_involutive]. Qed.
+
+Lemma of_inj d d' : of_hexadecimal d = of_hexadecimal d' -> dnorm d = dnorm d'.
+Proof.
+ intro H.
+ apply (@f_equal _ _ (fun x => match x with Some x => x | _ => d end)
+ (Some (dnorm d)) (Some (dnorm d'))).
+ now rewrite <- !to_of, H.
+Qed.
+
+Lemma of_iff d d' : of_hexadecimal d = of_hexadecimal d' <-> dnorm d = dnorm d'.
+Proof.
+ split. apply of_inj. intros E. rewrite <- of_hexadecimal_dnorm, E.
+ apply of_hexadecimal_dnorm.
+Qed.
diff --git a/theories/Numbers/HexadecimalZ.v b/theories/Numbers/HexadecimalZ.v
index c5ed0b5b28..1d78ad1ad2 100644
--- a/theories/Numbers/HexadecimalZ.v
+++ b/theories/Numbers/HexadecimalZ.v
@@ -80,9 +80,11 @@ Lemma of_hex_uint_iter_D0 d n :
Z.of_hex_uint (app d (Nat.iter n D0 Nil))
= Nat.iter n (Z.mul 0x10) (Z.of_hex_uint d).
Proof.
- unfold Z.of_hex_uint.
- unfold app; rewrite <-rev_revapp.
- rewrite Unsigned.of_lu_rev, Unsigned.of_lu_revapp.
+ rewrite <-(rev_rev (app _ _)), <-(of_list_to_list (rev (app _ _))).
+ rewrite rev_spec, app_spec, List.rev_app_distr.
+ rewrite <-!rev_spec, <-app_spec, of_list_to_list.
+ unfold Z.of_hex_uint; rewrite Unsigned.of_lu_rev.
+ unfold app; rewrite Unsigned.of_lu_revapp, !rev_rev.
rewrite <-!Unsigned.of_lu_rev, !rev_rev.
assert (H' : Pos.of_hex_uint (Nat.iter n D0 Nil) = 0%N).
{ now induction n; [|rewrite Unsigned.nat_iter_S]. }
@@ -140,3 +142,22 @@ Qed.
Lemma double_to_hex_int n :
double (Z.to_hex_int n) = Z.to_hex_int (Z.double n).
Proof. now rewrite <-(of_to n), <-of_hex_int_double, !to_of, double_norm. Qed.
+
+Lemma nztail_to_hex_uint_pow16 n :
+ Hexadecimal.nztail (Pos.to_hex_uint (Nat.iter n (Pos.mul 16) 1%positive))
+ = (D1 Nil, n).
+Proof.
+ case n as [|n]; [now simpl|].
+ rewrite <-(Nat2Pos.id (S n)); [|now simpl].
+ generalize (Pos.of_nat (S n)); clear n; intro p.
+ induction (Pos.to_nat p); [now simpl|].
+ rewrite Unsigned.nat_iter_S.
+ unfold Pos.to_hex_uint.
+ change (Pos.to_little_hex_uint _)
+ with (Unsigned.to_lu (16 * N.pos (Nat.iter n (Pos.mul 16) 1%positive))).
+ rewrite Unsigned.to_lhex_tenfold.
+ revert IHn; unfold Pos.to_hex_uint.
+ unfold Hexadecimal.nztail; rewrite !rev_rev; simpl.
+ set (f'' := _ (Pos.to_little_hex_uint _)).
+ now case f''; intros r n' H; inversion H.
+Qed.
diff --git a/theories/Numbers/Integer/Abstract/ZAdd.v b/theories/Numbers/Integer/Abstract/ZAdd.v
index 2361d59c26..0c097b6773 100644
--- a/theories/Numbers/Integer/Abstract/ZAdd.v
+++ b/theories/Numbers/Integer/Abstract/ZAdd.v
@@ -20,159 +20,157 @@ Include ZBaseProp Z.
Hint Rewrite opp_0 : nz.
-Theorem add_pred_l : forall n m, P n + m == P (n + m).
+Theorem add_pred_l n m : P n + m == P (n + m).
Proof.
-intros n m.
rewrite <- (succ_pred n) at 2.
now rewrite add_succ_l, pred_succ.
Qed.
-Theorem add_pred_r : forall n m, n + P m == P (n + m).
+Theorem add_pred_r n m : n + P m == P (n + m).
Proof.
-intros n m; rewrite 2 (add_comm n); apply add_pred_l.
+rewrite 2 (add_comm n); apply add_pred_l.
Qed.
-Theorem add_opp_r : forall n m, n + (- m) == n - m.
+Theorem add_opp_r n m : n + (- m) == n - m.
Proof.
nzinduct m.
now nzsimpl.
intro m. rewrite opp_succ, sub_succ_r, add_pred_r. now rewrite pred_inj_wd.
Qed.
-Theorem sub_0_l : forall n, 0 - n == - n.
+Theorem sub_0_l n : 0 - n == - n.
Proof.
-intro n; rewrite <- add_opp_r; now rewrite add_0_l.
+rewrite <- add_opp_r; now rewrite add_0_l.
Qed.
-Theorem sub_succ_l : forall n m, S n - m == S (n - m).
+Theorem sub_succ_l n m : S n - m == S (n - m).
Proof.
-intros n m; rewrite <- 2 add_opp_r; now rewrite add_succ_l.
+rewrite <- 2 add_opp_r; now rewrite add_succ_l.
Qed.
-Theorem sub_pred_l : forall n m, P n - m == P (n - m).
+Theorem sub_pred_l n m : P n - m == P (n - m).
Proof.
-intros n m. rewrite <- (succ_pred n) at 2.
+rewrite <- (succ_pred n) at 2.
rewrite sub_succ_l; now rewrite pred_succ.
Qed.
-Theorem sub_pred_r : forall n m, n - (P m) == S (n - m).
+Theorem sub_pred_r n m : n - (P m) == S (n - m).
Proof.
-intros n m. rewrite <- (succ_pred m) at 2.
+rewrite <- (succ_pred m) at 2.
rewrite sub_succ_r; now rewrite succ_pred.
Qed.
-Theorem opp_pred : forall n, - (P n) == S (- n).
+Theorem opp_pred n : - (P n) == S (- n).
Proof.
-intro n. rewrite <- (succ_pred n) at 2.
+rewrite <- (succ_pred n) at 2.
rewrite opp_succ. now rewrite succ_pred.
Qed.
-Theorem sub_diag : forall n, n - n == 0.
+Theorem sub_diag n : n - n == 0.
Proof.
nzinduct n.
now nzsimpl.
intro n. rewrite sub_succ_r, sub_succ_l; now rewrite pred_succ.
Qed.
-Theorem add_opp_diag_l : forall n, - n + n == 0.
+Theorem add_opp_diag_l n : - n + n == 0.
Proof.
-intro n; now rewrite add_comm, add_opp_r, sub_diag.
+now rewrite add_comm, add_opp_r, sub_diag.
Qed.
-Theorem add_opp_diag_r : forall n, n + (- n) == 0.
+Theorem add_opp_diag_r n : n + (- n) == 0.
Proof.
-intro n; rewrite add_comm; apply add_opp_diag_l.
+rewrite add_comm; apply add_opp_diag_l.
Qed.
-Theorem add_opp_l : forall n m, - m + n == n - m.
+Theorem add_opp_l n m : - m + n == n - m.
Proof.
-intros n m; rewrite <- add_opp_r; now rewrite add_comm.
+rewrite <- add_opp_r; now rewrite add_comm.
Qed.
-Theorem add_sub_assoc : forall n m p, n + (m - p) == (n + m) - p.
+Theorem add_sub_assoc n m p : n + (m - p) == (n + m) - p.
Proof.
-intros n m p; rewrite <- 2 add_opp_r; now rewrite add_assoc.
+rewrite <- 2 add_opp_r; now rewrite add_assoc.
Qed.
-Theorem opp_involutive : forall n, - (- n) == n.
+Theorem opp_involutive n : - (- n) == n.
Proof.
nzinduct n.
now nzsimpl.
intro n. rewrite opp_succ, opp_pred. now rewrite succ_inj_wd.
Qed.
-Theorem opp_add_distr : forall n m, - (n + m) == - n + (- m).
+Theorem opp_add_distr n m : - (n + m) == - n + (- m).
Proof.
-intros n m; nzinduct n.
+nzinduct n.
now nzsimpl.
intro n. rewrite add_succ_l; do 2 rewrite opp_succ; rewrite add_pred_l.
now rewrite pred_inj_wd.
Qed.
-Theorem opp_sub_distr : forall n m, - (n - m) == - n + m.
+Theorem opp_sub_distr n m : - (n - m) == - n + m.
Proof.
-intros n m; rewrite <- add_opp_r, opp_add_distr.
+rewrite <- add_opp_r, opp_add_distr.
now rewrite opp_involutive.
Qed.
-Theorem opp_inj : forall n m, - n == - m -> n == m.
+Theorem opp_inj n m : - n == - m -> n == m.
Proof.
-intros n m H. apply opp_wd in H. now rewrite 2 opp_involutive in H.
+intros H. apply opp_wd in H. now rewrite 2 opp_involutive in H.
Qed.
-Theorem opp_inj_wd : forall n m, - n == - m <-> n == m.
+Theorem opp_inj_wd n m : - n == - m <-> n == m.
Proof.
-intros n m; split; [apply opp_inj | intros; now f_equiv].
+split; [apply opp_inj | intros; now f_equiv].
Qed.
-Theorem eq_opp_l : forall n m, - n == m <-> n == - m.
+Theorem eq_opp_l n m : - n == m <-> n == - m.
Proof.
-intros n m. now rewrite <- (opp_inj_wd (- n) m), opp_involutive.
+now rewrite <- (opp_inj_wd (- n) m), opp_involutive.
Qed.
-Theorem eq_opp_r : forall n m, n == - m <-> - n == m.
+Theorem eq_opp_r n m : n == - m <-> - n == m.
Proof.
symmetry; apply eq_opp_l.
Qed.
-Theorem sub_add_distr : forall n m p, n - (m + p) == (n - m) - p.
+Theorem sub_add_distr n m p : n - (m + p) == (n - m) - p.
Proof.
-intros n m p; rewrite <- add_opp_r, opp_add_distr, add_assoc.
+rewrite <- add_opp_r, opp_add_distr, add_assoc.
now rewrite 2 add_opp_r.
Qed.
-Theorem sub_sub_distr : forall n m p, n - (m - p) == (n - m) + p.
+Theorem sub_sub_distr n m p : n - (m - p) == (n - m) + p.
Proof.
-intros n m p; rewrite <- add_opp_r, opp_sub_distr, add_assoc.
+rewrite <- add_opp_r, opp_sub_distr, add_assoc.
now rewrite add_opp_r.
Qed.
-Theorem sub_opp_l : forall n m, - n - m == - m - n.
+Theorem sub_opp_l n m : - n - m == - m - n.
Proof.
-intros n m. rewrite <- 2 add_opp_r. now rewrite add_comm.
+rewrite <- 2 add_opp_r. now rewrite add_comm.
Qed.
-Theorem sub_opp_r : forall n m, n - (- m) == n + m.
+Theorem sub_opp_r n m : n - (- m) == n + m.
Proof.
-intros n m; rewrite <- add_opp_r; now rewrite opp_involutive.
+rewrite <- add_opp_r; now rewrite opp_involutive.
Qed.
-Theorem add_sub_swap : forall n m p, n + m - p == n - p + m.
+Theorem add_sub_swap n m p : n + m - p == n - p + m.
Proof.
-intros n m p. rewrite <- add_sub_assoc, <- (add_opp_r n p), <- add_assoc.
+rewrite <- add_sub_assoc, <- (add_opp_r n p), <- add_assoc.
now rewrite add_opp_l.
Qed.
-Theorem sub_cancel_l : forall n m p, n - m == n - p <-> m == p.
+Theorem sub_cancel_l n m p : n - m == n - p <-> m == p.
Proof.
-intros n m p. rewrite <- (add_cancel_l (n - m) (n - p) (- n)).
+rewrite <- (add_cancel_l (n - m) (n - p) (- n)).
rewrite 2 add_sub_assoc. rewrite add_opp_diag_l; rewrite 2 sub_0_l.
apply opp_inj_wd.
Qed.
-Theorem sub_cancel_r : forall n m p, n - p == m - p <-> n == m.
+Theorem sub_cancel_r n m p : n - p == m - p <-> n == m.
Proof.
-intros n m p.
stepl (n - p + p == m - p + p) by apply add_cancel_r.
now do 2 rewrite <- sub_sub_distr, sub_diag, sub_0_r.
Qed.
@@ -182,16 +180,15 @@ Qed.
in the original equation ([add] or [sub]) and the indication
whether the left or right term is moved. *)
-Theorem add_move_l : forall n m p, n + m == p <-> m == p - n.
+Theorem add_move_l n m p : n + m == p <-> m == p - n.
Proof.
-intros n m p.
stepl (n + m - n == p - n) by apply sub_cancel_r.
now rewrite add_comm, <- add_sub_assoc, sub_diag, add_0_r.
Qed.
-Theorem add_move_r : forall n m p, n + m == p <-> n == p - m.
+Theorem add_move_r n m p : n + m == p <-> n == p - m.
Proof.
-intros n m p; rewrite add_comm; now apply add_move_l.
+rewrite add_comm; now apply add_move_l.
Qed.
(** The two theorems above do not allow rewriting subformulas of the
@@ -199,98 +196,98 @@ Qed.
right-hand side of the equation. Hence the following two
theorems. *)
-Theorem sub_move_l : forall n m p, n - m == p <-> - m == p - n.
+Theorem sub_move_l n m p : n - m == p <-> - m == p - n.
Proof.
-intros n m p; rewrite <- (add_opp_r n m); apply add_move_l.
+rewrite <- (add_opp_r n m); apply add_move_l.
Qed.
-Theorem sub_move_r : forall n m p, n - m == p <-> n == p + m.
+Theorem sub_move_r n m p : n - m == p <-> n == p + m.
Proof.
-intros n m p; rewrite <- (add_opp_r n m). now rewrite add_move_r, sub_opp_r.
+rewrite <- (add_opp_r n m). now rewrite add_move_r, sub_opp_r.
Qed.
-Theorem add_move_0_l : forall n m, n + m == 0 <-> m == - n.
+Theorem add_move_0_l n m : n + m == 0 <-> m == - n.
Proof.
-intros n m; now rewrite add_move_l, sub_0_l.
+now rewrite add_move_l, sub_0_l.
Qed.
-Theorem add_move_0_r : forall n m, n + m == 0 <-> n == - m.
+Theorem add_move_0_r n m : n + m == 0 <-> n == - m.
Proof.
-intros n m; now rewrite add_move_r, sub_0_l.
+now rewrite add_move_r, sub_0_l.
Qed.
-Theorem sub_move_0_l : forall n m, n - m == 0 <-> - m == - n.
+Theorem sub_move_0_l n m : n - m == 0 <-> - m == - n.
Proof.
-intros n m. now rewrite sub_move_l, sub_0_l.
+now rewrite sub_move_l, sub_0_l.
Qed.
-Theorem sub_move_0_r : forall n m, n - m == 0 <-> n == m.
+Theorem sub_move_0_r n m : n - m == 0 <-> n == m.
Proof.
-intros n m. now rewrite sub_move_r, add_0_l.
+now rewrite sub_move_r, add_0_l.
Qed.
(** The following section is devoted to cancellation of like
terms. The name includes the first operator and the position of
the term being canceled. *)
-Theorem add_simpl_l : forall n m, n + m - n == m.
+Theorem add_simpl_l n m : n + m - n == m.
Proof.
-intros; now rewrite add_sub_swap, sub_diag, add_0_l.
+now rewrite add_sub_swap, sub_diag, add_0_l.
Qed.
-Theorem add_simpl_r : forall n m, n + m - m == n.
+Theorem add_simpl_r n m : n + m - m == n.
Proof.
-intros; now rewrite <- add_sub_assoc, sub_diag, add_0_r.
+now rewrite <- add_sub_assoc, sub_diag, add_0_r.
Qed.
-Theorem sub_simpl_l : forall n m, - n - m + n == - m.
+Theorem sub_simpl_l n m : - n - m + n == - m.
Proof.
-intros; now rewrite <- add_sub_swap, add_opp_diag_l, sub_0_l.
+now rewrite <- add_sub_swap, add_opp_diag_l, sub_0_l.
Qed.
-Theorem sub_simpl_r : forall n m, n - m + m == n.
+Theorem sub_simpl_r n m : n - m + m == n.
Proof.
-intros; now rewrite <- sub_sub_distr, sub_diag, sub_0_r.
+now rewrite <- sub_sub_distr, sub_diag, sub_0_r.
Qed.
-Theorem sub_add : forall n m, m - n + n == m.
+Theorem sub_add n m : m - n + n == m.
Proof.
- intros. now rewrite <- add_sub_swap, add_simpl_r.
+now rewrite <- add_sub_swap, add_simpl_r.
Qed.
(** Now we have two sums or differences; the name includes the two
operators and the position of the terms being canceled *)
-Theorem add_add_simpl_l_l : forall n m p, (n + m) - (n + p) == m - p.
+Theorem add_add_simpl_l_l n m p : (n + m) - (n + p) == m - p.
Proof.
-intros n m p. now rewrite (add_comm n m), <- add_sub_assoc,
+now rewrite (add_comm n m), <- add_sub_assoc,
sub_add_distr, sub_diag, sub_0_l, add_opp_r.
Qed.
-Theorem add_add_simpl_l_r : forall n m p, (n + m) - (p + n) == m - p.
+Theorem add_add_simpl_l_r n m p : (n + m) - (p + n) == m - p.
Proof.
-intros n m p. rewrite (add_comm p n); apply add_add_simpl_l_l.
+rewrite (add_comm p n); apply add_add_simpl_l_l.
Qed.
-Theorem add_add_simpl_r_l : forall n m p, (n + m) - (m + p) == n - p.
+Theorem add_add_simpl_r_l n m p : (n + m) - (m + p) == n - p.
Proof.
-intros n m p. rewrite (add_comm n m); apply add_add_simpl_l_l.
+rewrite (add_comm n m); apply add_add_simpl_l_l.
Qed.
-Theorem add_add_simpl_r_r : forall n m p, (n + m) - (p + m) == n - p.
+Theorem add_add_simpl_r_r n m p : (n + m) - (p + m) == n - p.
Proof.
-intros n m p. rewrite (add_comm p m); apply add_add_simpl_r_l.
+rewrite (add_comm p m); apply add_add_simpl_r_l.
Qed.
-Theorem sub_add_simpl_r_l : forall n m p, (n - m) + (m + p) == n + p.
+Theorem sub_add_simpl_r_l n m p : (n - m) + (m + p) == n + p.
Proof.
-intros n m p. now rewrite <- sub_sub_distr, sub_add_distr, sub_diag,
+now rewrite <- sub_sub_distr, sub_add_distr, sub_diag,
sub_0_l, sub_opp_r.
Qed.
-Theorem sub_add_simpl_r_r : forall n m p, (n - m) + (p + m) == n + p.
+Theorem sub_add_simpl_r_r n m p : (n - m) + (p + m) == n + p.
Proof.
-intros n m p. rewrite (add_comm p m); apply sub_add_simpl_r_l.
+rewrite (add_comm p m); apply sub_add_simpl_r_l.
Qed.
(** Of course, there are many other variants *)
diff --git a/theories/Numbers/Integer/Abstract/ZAddOrder.v b/theories/Numbers/Integer/Abstract/ZAddOrder.v
index 40a37be5f9..5a293c6483 100644
--- a/theories/Numbers/Integer/Abstract/ZAddOrder.v
+++ b/theories/Numbers/Integer/Abstract/ZAddOrder.v
@@ -241,25 +241,25 @@ Qed.
Theorem sub_neg_cases : forall n m, n - m < 0 -> n < 0 \/ 0 < m.
Proof.
-intros.
+intros n m ?.
rewrite <- (opp_neg_pos m). apply add_neg_cases. now rewrite add_opp_r.
Qed.
Theorem sub_pos_cases : forall n m, 0 < n - m -> 0 < n \/ m < 0.
Proof.
-intros.
+intros n m ?.
rewrite <- (opp_pos_neg m). apply add_pos_cases. now rewrite add_opp_r.
Qed.
Theorem sub_nonpos_cases : forall n m, n - m <= 0 -> n <= 0 \/ 0 <= m.
Proof.
-intros.
+intros n m ?.
rewrite <- (opp_nonpos_nonneg m). apply add_nonpos_cases. now rewrite add_opp_r.
Qed.
Theorem sub_nonneg_cases : forall n m, 0 <= n - m -> 0 <= n \/ m <= 0.
Proof.
-intros.
+intros n m ?.
rewrite <- (opp_nonneg_nonpos m). apply add_nonneg_cases. now rewrite add_opp_r.
Qed.
diff --git a/theories/Numbers/Integer/Abstract/ZBits.v b/theories/Numbers/Integer/Abstract/ZBits.v
index 0f40d3d7b6..4d2361689d 100644
--- a/theories/Numbers/Integer/Abstract/ZBits.v
+++ b/theories/Numbers/Integer/Abstract/ZBits.v
@@ -244,7 +244,7 @@ Qed.
Lemma bit0_odd : forall a, a.[0] = odd a.
Proof.
- intros. symmetry.
+ intros a. symmetry.
destruct (exists_div2 a) as (a' & b & EQ).
rewrite EQ, testbit_0_r, add_comm, odd_add_mul_2.
destruct b; simpl; apply odd_1 || apply odd_0.
@@ -428,14 +428,14 @@ Qed.
Lemma mul_pow2_bits : forall a n m, 0<=n -> (a*2^n).[m] = a.[m-n].
Proof.
- intros.
+ intros a n m ?.
rewrite <- (add_simpl_r m n) at 1. rewrite add_sub_swap, add_comm.
now apply mul_pow2_bits_add.
Qed.
Lemma mul_pow2_bits_low : forall a n m, m<n -> (a*2^n).[m] = false.
Proof.
- intros.
+ intros a n m ?.
destruct (le_gt_cases 0 n).
rewrite mul_pow2_bits by trivial.
apply testbit_neg_r. now apply lt_sub_0.
@@ -561,7 +561,10 @@ Proof.
split. apply bits_inj'. intros EQ n Hn; now rewrite EQ.
Qed.
-Ltac bitwise := apply bits_inj'; intros ?m ?Hm; autorewrite with bitwise.
+Tactic Notation "bitwise" "as" simple_intropattern(m) simple_intropattern(Hm)
+ := apply bits_inj'; intros m Hm; autorewrite with bitwise.
+
+Ltac bitwise := bitwise as ?m ?Hm.
Hint Rewrite lxor_spec lor_spec land_spec ldiff_spec bits_0 : bitwise.
@@ -619,7 +622,7 @@ Qed.
Lemma shiftl_spec : forall a n m, 0<=m -> (a << n).[m] = a.[m-n].
Proof.
- intros.
+ intros a n m ?.
destruct (le_gt_cases n m).
now apply shiftl_spec_high.
rewrite shiftl_spec_low, testbit_neg_r; trivial. now apply lt_sub_0.
@@ -693,7 +696,7 @@ Qed.
Lemma shiftl_shiftl : forall a n m, 0<=n ->
(a << n) << m == a << (n+m).
Proof.
- intros a n p Hn. bitwise.
+ intros a n p Hn. bitwise as m Hm.
rewrite 2 (shiftl_spec _ _ m) by trivial.
rewrite add_comm, sub_add_distr.
destruct (le_gt_cases 0 (m-p)) as [H|H].
@@ -745,8 +748,8 @@ Qed.
Lemma shiftl_0_l : forall n, 0 << n == 0.
Proof.
- intros.
- destruct (le_ge_cases 0 n).
+ intros n.
+ destruct (le_ge_cases 0 n) as [H|H].
rewrite shiftl_mul_pow2 by trivial. now nzsimpl.
rewrite shiftl_div_pow2 by trivial.
rewrite <- opp_nonneg_nonpos in H. nzsimpl; order_nz.
@@ -901,7 +904,7 @@ Qed.
Lemma lor_eq_0_l : forall a b, lor a b == 0 -> a == 0.
Proof.
- intros a b H. bitwise.
+ intros a b H. bitwise as m ?.
apply (orb_false_iff a.[m] b.[m]).
now rewrite <- lor_spec, H, bits_0.
Qed.
@@ -909,7 +912,7 @@ Qed.
Lemma lor_eq_0_iff : forall a b, lor a b == 0 <-> a == 0 /\ b == 0.
Proof.
intros a b. split.
- split. now apply lor_eq_0_l in H.
+ intro H; split. now apply lor_eq_0_l in H.
rewrite lor_comm in H. now apply lor_eq_0_l in H.
intros (EQ,EQ'). now rewrite EQ, lor_0_l.
Qed.
@@ -1022,13 +1025,13 @@ Proof. unfold clearbit. solve_proper. Qed.
Lemma pow2_bits_true : forall n, 0<=n -> (2^n).[n] = true.
Proof.
- intros. rewrite <- (mul_1_l (2^n)).
+ intros n ?. rewrite <- (mul_1_l (2^n)).
now rewrite mul_pow2_bits, sub_diag, bit0_odd, odd_1.
Qed.
Lemma pow2_bits_false : forall n m, n~=m -> (2^n).[m] = false.
Proof.
- intros.
+ intros n m ?.
destruct (le_gt_cases 0 n); [|now rewrite pow_neg_r, bits_0].
destruct (le_gt_cases n m).
rewrite <- (mul_1_l (2^n)), mul_pow2_bits; trivial.
@@ -1073,7 +1076,7 @@ Qed.
Lemma clearbit_eqb : forall a n m,
(clearbit a n).[m] = a.[m] && negb (eqb n m).
Proof.
- intros.
+ intros a n m.
destruct (le_gt_cases 0 m); [| now rewrite 2 testbit_neg_r].
rewrite clearbit_spec', ldiff_spec. f_equal. f_equal.
destruct (le_gt_cases 0 n) as [Hn|Hn].
@@ -1090,7 +1093,7 @@ Qed.
Lemma clearbit_eq : forall a n, (clearbit a n).[n] = false.
Proof.
- intros. rewrite clearbit_eqb, (proj2 (eqb_eq _ _) (eq_refl n)).
+ intros a n. rewrite clearbit_eqb, (proj2 (eqb_eq _ _) (eq_refl n)).
apply andb_false_r.
Qed.
@@ -1161,7 +1164,7 @@ Proof. unfold lnot. solve_proper. Qed.
Lemma lnot_spec : forall a n, 0<=n -> (lnot a).[n] = negb a.[n].
Proof.
- intros. unfold lnot. rewrite <- (opp_involutive a) at 2.
+ intros a n ?. unfold lnot. rewrite <- (opp_involutive a) at 2.
rewrite bits_opp, negb_involutive; trivial.
Qed.
@@ -1214,7 +1217,7 @@ Qed.
Lemma lor_lnot_diag : forall a, lor a (lnot a) == -1.
Proof.
- intros a. bitwise. rewrite lnot_spec, bits_m1; trivial.
+ intros a. bitwise as m ?. rewrite lnot_spec, bits_m1; trivial.
now destruct a.[m].
Qed.
@@ -1267,7 +1270,7 @@ Qed.
Lemma lxor_m1_r : forall a, lxor a (-1) == lnot a.
Proof.
- intros. now rewrite <- (lxor_0_r (lnot a)), <- lnot_m1, lxor_lnot_lnot.
+ intros a. now rewrite <- (lxor_0_r (lnot a)), <- lnot_m1, lxor_lnot_lnot.
Qed.
Lemma lxor_m1_l : forall a, lxor (-1) a == lnot a.
@@ -1278,7 +1281,7 @@ Qed.
Lemma lxor_lor : forall a b, land a b == 0 ->
lxor a b == lor a b.
Proof.
- intros a b H. bitwise.
+ intros a b H. bitwise as m ?.
assert (a.[m] && b.[m] = false)
by now rewrite <- land_spec, H, bits_0.
now destruct a.[m], b.[m].
@@ -1299,7 +1302,7 @@ Proof. unfold ones. solve_proper. Qed.
Lemma ones_equiv : forall n, ones n == P (2^n).
Proof.
- intros. unfold ones.
+ intros n. unfold ones.
destruct (le_gt_cases 0 n).
now rewrite shiftl_mul_pow2, mul_1_l.
f_equiv. rewrite pow_neg_r; trivial.
@@ -1367,7 +1370,7 @@ Qed.
Lemma lor_ones_low : forall a n, 0<=a -> log2 a < n ->
lor a (ones n) == ones n.
Proof.
- intros a n Ha H. bitwise. destruct (le_gt_cases n m).
+ intros a n Ha H. bitwise as m ?. destruct (le_gt_cases n m).
rewrite ones_spec_high, bits_above_log2; try split; trivial.
now apply lt_le_trans with n.
apply le_trans with (log2 a); order_pos.
@@ -1376,7 +1379,7 @@ Qed.
Lemma land_ones : forall a n, 0<=n -> land a (ones n) == a mod 2^n.
Proof.
- intros a n Hn. bitwise. destruct (le_gt_cases n m).
+ intros a n Hn. bitwise as m ?. destruct (le_gt_cases n m).
rewrite ones_spec_high, mod_pow2_bits_high, andb_false_r;
try split; trivial.
rewrite ones_spec_low, mod_pow2_bits_low, andb_true_r;
@@ -1396,7 +1399,7 @@ Qed.
Lemma ldiff_ones_r : forall a n, 0<=n ->
ldiff a (ones n) == (a >> n) << n.
Proof.
- intros a n Hn. bitwise. destruct (le_gt_cases n m).
+ intros a n Hn. bitwise as m ?. destruct (le_gt_cases n m).
rewrite ones_spec_high, shiftl_spec_high, shiftr_spec; trivial.
rewrite sub_add; trivial. apply andb_true_r.
now apply le_0_sub.
@@ -1408,7 +1411,7 @@ Qed.
Lemma ldiff_ones_r_low : forall a n, 0<=a -> log2 a < n ->
ldiff a (ones n) == 0.
Proof.
- intros a n Ha H. bitwise. destruct (le_gt_cases n m).
+ intros a n Ha H. bitwise as m ?. destruct (le_gt_cases n m).
rewrite ones_spec_high, bits_above_log2; trivial.
now apply lt_le_trans with n.
split; trivial. now apply le_trans with (log2 a); order_pos.
@@ -1418,7 +1421,7 @@ Qed.
Lemma ldiff_ones_l_low : forall a n, 0<=a -> log2 a < n ->
ldiff (ones n) a == lxor a (ones n).
Proof.
- intros a n Ha H. bitwise. destruct (le_gt_cases n m).
+ intros a n Ha H. bitwise as m ?. destruct (le_gt_cases n m).
rewrite ones_spec_high, bits_above_log2; trivial.
now apply lt_le_trans with n.
split; trivial. now apply le_trans with (log2 a); order_pos.
@@ -1585,7 +1588,7 @@ Qed.
Lemma log2_shiftr : forall a n, 0<a -> log2 (a >> n) == max 0 (log2 a - n).
Proof.
intros a n Ha.
- destruct (le_gt_cases 0 (log2 a - n));
+ destruct (le_gt_cases 0 (log2 a - n)) as [H|H];
[rewrite max_r | rewrite max_l]; try order.
apply log2_bits_unique.
now rewrite shiftr_spec, sub_add, bit_log2.
@@ -1698,7 +1701,7 @@ Qed.
Lemma add_carry_div2 : forall a b (c0:bool),
(a + b + c0)/2 == a/2 + b/2 + nextcarry a.[0] b.[0] c0.
Proof.
- intros.
+ intros a b c0.
rewrite <- add3_bits_div2.
rewrite (add_comm ((a/2)+_)).
rewrite <- div_add by order'.
@@ -1767,7 +1770,7 @@ Proof.
apply div_lt_upper_bound. order'. now rewrite <- pow_succ_r.
exists (c0 + 2*c). repeat split.
(* step, add *)
- bitwise.
+ bitwise as m Hm.
le_elim Hm.
rewrite <- (succ_pred m), lt_succ_r in Hm.
rewrite <- (succ_pred m), <- !div2_bits, <- 2 lxor_spec by trivial.
@@ -1777,7 +1780,7 @@ Proof.
now rewrite add_b2z_double_bit0, add3_bit0, b2z_bit0.
(* step, carry *)
rewrite add_b2z_double_div2.
- bitwise.
+ bitwise as m Hm.
le_elim Hm.
rewrite <- (succ_pred m), lt_succ_r in Hm.
rewrite <- (succ_pred m), <- !div2_bits, IH2 by trivial.
@@ -1905,7 +1908,7 @@ Proof.
rewrite sub_add.
symmetry.
rewrite add_nocarry_lxor; trivial.
- bitwise.
+ bitwise as m ?.
apply bits_inj_iff in H. specialize (H m).
rewrite ldiff_spec, bits_0 in H.
now destruct a.[m], b.[m].
@@ -1938,7 +1941,7 @@ Lemma add_nocarry_mod_lt_pow2 : forall a b n, 0<=n -> land a b == 0 ->
Proof.
intros a b n Hn H.
apply add_nocarry_lt_pow2.
- bitwise.
+ bitwise as m ?.
destruct (le_gt_cases n m).
rewrite mod_pow2_bits_high; now split.
now rewrite !mod_pow2_bits_low, <- land_spec, H, bits_0.
diff --git a/theories/Numbers/Integer/Abstract/ZDivFloor.v b/theories/Numbers/Integer/Abstract/ZDivFloor.v
index 44cba37eb2..d28d010ae8 100644
--- a/theories/Numbers/Integer/Abstract/ZDivFloor.v
+++ b/theories/Numbers/Integer/Abstract/ZDivFloor.v
@@ -51,7 +51,7 @@ Qed.
Lemma mod_bound_abs :
forall a b, b~=0 -> abs (a mod b) < abs b.
Proof.
-intros.
+intros a b **.
destruct (abs_spec b) as [(LE,EQ)|(LE,EQ)]; rewrite EQ.
destruct (mod_pos_bound a b). order. now rewrite abs_eq.
destruct (mod_neg_bound a b). order. rewrite abs_neq; trivial.
@@ -87,11 +87,11 @@ Qed.
Theorem div_unique_pos:
forall a b q r, 0<=r<b -> a == b*q + r -> q == a/b.
-Proof. intros; apply div_unique with r; auto. Qed.
+Proof. intros a b q r **; apply div_unique with r; auto. Qed.
Theorem div_unique_neg:
forall a b q r, b<r<=0 -> a == b*q + r -> q == a/b.
-Proof. intros; apply div_unique with r; auto. Qed.
+Proof. intros a b q r **; apply div_unique with r; auto. Qed.
Theorem mod_unique:
forall a b q r, (0<=r<b \/ b<r<=0) -> a == b*q + r -> r == a mod b.
@@ -106,11 +106,11 @@ Qed.
Theorem mod_unique_pos:
forall a b q r, 0<=r<b -> a == b*q + r -> r == a mod b.
-Proof. intros; apply mod_unique with q; auto. Qed.
+Proof. intros a b q r **; apply mod_unique with q; auto. Qed.
Theorem mod_unique_neg:
forall a b q r, b<r<=0 -> a == b*q + r -> r == a mod b.
-Proof. intros; apply mod_unique with q; auto. Qed.
+Proof. intros a b q r **; apply mod_unique with q; auto. Qed.
(** Sign rules *)
@@ -121,7 +121,7 @@ Ltac pos_or_neg a :=
Fact mod_bound_or : forall a b, b~=0 -> 0<=a mod b<b \/ b<a mod b<=0.
Proof.
-intros.
+intros a b **.
destruct (lt_ge_cases 0 b); [left|right].
apply mod_pos_bound; trivial. apply mod_neg_bound; order.
Qed.
@@ -129,7 +129,7 @@ Qed.
Fact opp_mod_bound_or : forall a b, b~=0 ->
0 <= -(a mod b) < -b \/ -b < -(a mod b) <= 0.
Proof.
-intros.
+intros a b **.
destruct (lt_ge_cases 0 b); [right|left].
rewrite <- opp_lt_mono, opp_nonpos_nonneg.
destruct (mod_pos_bound a b); intuition; order.
@@ -139,14 +139,14 @@ Qed.
Lemma div_opp_opp : forall a b, b~=0 -> -a/-b == a/b.
Proof.
-intros. symmetry. apply div_unique with (- (a mod b)).
+intros a b **. symmetry. apply div_unique with (- (a mod b)).
now apply opp_mod_bound_or.
rewrite mul_opp_l, <- opp_add_distr, <- div_mod; order.
Qed.
Lemma mod_opp_opp : forall a b, b~=0 -> (-a) mod (-b) == - (a mod b).
Proof.
-intros. symmetry. apply mod_unique with (a/b).
+intros a b **. symmetry. apply mod_unique with (a/b).
now apply opp_mod_bound_or.
rewrite mul_opp_l, <- opp_add_distr, <- div_mod; order.
Qed.
@@ -200,28 +200,28 @@ Qed.
Lemma div_opp_r_z :
forall a b, b~=0 -> a mod b == 0 -> a/(-b) == -(a/b).
Proof.
-intros. rewrite <- (opp_involutive a) at 1.
+intros a b **. rewrite <- (opp_involutive a) at 1.
rewrite div_opp_opp; auto using div_opp_l_z.
Qed.
Lemma div_opp_r_nz :
forall a b, b~=0 -> a mod b ~= 0 -> a/(-b) == -(a/b)-1.
Proof.
-intros. rewrite <- (opp_involutive a) at 1.
+intros a b **. rewrite <- (opp_involutive a) at 1.
rewrite div_opp_opp; auto using div_opp_l_nz.
Qed.
Lemma mod_opp_r_z :
forall a b, b~=0 -> a mod b == 0 -> a mod (-b) == 0.
Proof.
-intros. rewrite <- (opp_involutive a) at 1.
+intros a b **. rewrite <- (opp_involutive a) at 1.
now rewrite mod_opp_opp, mod_opp_l_z, opp_0.
Qed.
Lemma mod_opp_r_nz :
forall a b, b~=0 -> a mod b ~= 0 -> a mod (-b) == (a mod b) - b.
Proof.
-intros. rewrite <- (opp_involutive a) at 1.
+intros a b **. rewrite <- (opp_involutive a) at 1.
rewrite mod_opp_opp, mod_opp_l_nz by trivial.
now rewrite opp_sub_distr, add_comm, add_opp_r.
Qed.
@@ -247,7 +247,7 @@ Qed.
Lemma mod_sign_mul : forall a b, b~=0 -> 0 <= (a mod b) * b.
Proof.
-intros. destruct (lt_ge_cases 0 b).
+intros a b **. destruct (lt_ge_cases 0 b).
apply mul_nonneg_nonneg; destruct (mod_pos_bound a b); order.
apply mul_nonpos_nonpos; destruct (mod_neg_bound a b); order.
Qed.
@@ -256,7 +256,7 @@ Qed.
Lemma div_same : forall a, a~=0 -> a/a == 1.
Proof.
-intros. pos_or_neg a. apply div_same; order.
+intros a ?. pos_or_neg a. apply div_same; order.
rewrite <- div_opp_opp by trivial. now apply div_same.
Qed.
@@ -279,7 +279,7 @@ Proof. exact mod_small. Qed.
Lemma div_0_l: forall a, a~=0 -> 0/a == 0.
Proof.
-intros. pos_or_neg a. apply div_0_l; order.
+intros a ?. pos_or_neg a. apply div_0_l; order.
rewrite <- div_opp_opp, opp_0 by trivial. now apply div_0_l.
Qed.
@@ -308,7 +308,7 @@ Proof. exact mod_1_l. Qed.
Lemma div_mul : forall a b, b~=0 -> (a*b)/b == a.
Proof.
-intros. symmetry. apply div_unique with 0.
+intros a b ?. symmetry. apply div_unique with 0.
destruct (lt_ge_cases 0 b); [left|right]; split; order.
nzsimpl; apply mul_comm.
Qed.
@@ -350,7 +350,7 @@ Qed.
Lemma mod_small_iff : forall a b, b~=0 -> (a mod b == a <-> 0<=a<b \/ b<a<=0).
Proof.
-intros.
+intros a b **.
rewrite <- div_small_iff, mod_eq by trivial.
rewrite sub_move_r, <- (add_0_r a) at 1. rewrite add_cancel_l.
rewrite eq_sym_iff, eq_mul_0. tauto.
@@ -393,7 +393,7 @@ Qed.
Lemma mul_div_le : forall a b, 0<b -> b*(a/b) <= a.
Proof.
-intros.
+intros a b **.
rewrite (div_mod a b) at 2; try order.
rewrite <- (add_0_r (b*(a/b))) at 1.
rewrite <- add_le_mono_l.
@@ -412,7 +412,7 @@ Qed.
Lemma mul_succ_div_gt: forall a b, 0<b -> a < b*(S (a/b)).
Proof.
-intros.
+intros a b ?.
nzsimpl.
rewrite (div_mod a b) at 1; try order.
rewrite <- add_lt_mono_l.
@@ -432,7 +432,7 @@ Qed.
Lemma div_exact : forall a b, b~=0 -> (a == b*(a/b) <-> a mod b == 0).
Proof.
-intros.
+intros a b **.
rewrite (div_mod a b) at 1; try order.
rewrite <- (add_0_r (b*(a/b))) at 2.
apply add_cancel_l.
@@ -443,7 +443,7 @@ Qed.
Theorem div_lt_upper_bound:
forall a b q, 0<b -> a < b*q -> a/b < q.
Proof.
-intros.
+intros a b q **.
rewrite (mul_lt_mono_pos_l b) by trivial.
apply le_lt_trans with a; trivial.
now apply mul_div_le.
@@ -452,7 +452,7 @@ Qed.
Theorem div_le_upper_bound:
forall a b q, 0<b -> a <= b*q -> a/b <= q.
Proof.
-intros.
+intros a b q **.
rewrite <- (div_mul q b) by order.
apply div_le_mono; trivial. now rewrite mul_comm.
Qed.
@@ -460,7 +460,7 @@ Qed.
Theorem div_le_lower_bound:
forall a b q, 0<b -> b*q <= a -> q <= a/b.
Proof.
-intros.
+intros a b q **.
rewrite <- (div_mul q b) by order.
apply div_le_mono; trivial. now rewrite mul_comm.
Qed.
@@ -475,7 +475,7 @@ Proof. exact div_le_compat_l. Qed.
Lemma mod_add : forall a b c, c~=0 ->
(a + b * c) mod c == a mod c.
Proof.
-intros.
+intros a b c **.
symmetry.
apply mod_unique with (a/c+b); trivial.
now apply mod_bound_or.
@@ -486,7 +486,7 @@ Qed.
Lemma div_add : forall a b c, c~=0 ->
(a + b * c) / c == a / c + b.
Proof.
-intros.
+intros a b c **.
apply (mul_cancel_l _ _ c); try order.
apply (add_cancel_r _ _ ((a+b*c) mod c)).
rewrite <- div_mod, mod_add by order.
@@ -506,7 +506,7 @@ Qed.
Lemma div_mul_cancel_r : forall a b c, b~=0 -> c~=0 ->
(a*c)/(b*c) == a/b.
Proof.
-intros.
+intros a b c **.
symmetry.
apply div_unique with ((a mod b)*c).
(* ineqs *)
@@ -525,13 +525,13 @@ Qed.
Lemma div_mul_cancel_l : forall a b c, b~=0 -> c~=0 ->
(c*a)/(c*b) == a/b.
Proof.
-intros. rewrite !(mul_comm c); now apply div_mul_cancel_r.
+intros a b c **. rewrite !(mul_comm c); now apply div_mul_cancel_r.
Qed.
Lemma mul_mod_distr_l: forall a b c, b~=0 -> c~=0 ->
(c*a) mod (c*b) == c * (a mod b).
Proof.
-intros.
+intros a b c **.
rewrite <- (add_cancel_l _ _ ((c*b)* ((c*a)/(c*b)))).
rewrite <- div_mod.
rewrite div_mul_cancel_l by trivial.
@@ -543,7 +543,7 @@ Qed.
Lemma mul_mod_distr_r: forall a b c, b~=0 -> c~=0 ->
(a*c) mod (b*c) == (a mod b) * c.
Proof.
- intros. rewrite !(mul_comm _ c); now rewrite mul_mod_distr_l.
+ intros a b c **. rewrite !(mul_comm _ c); now rewrite mul_mod_distr_l.
Qed.
@@ -570,7 +570,7 @@ Qed.
Lemma mul_mod_idemp_r : forall a b n, n~=0 ->
(a*(b mod n)) mod n == (a*b) mod n.
Proof.
- intros. rewrite !(mul_comm a). now apply mul_mod_idemp_l.
+ intros a b n **. rewrite !(mul_comm a). now apply mul_mod_idemp_l.
Qed.
Theorem mul_mod: forall a b n, n~=0 ->
@@ -591,7 +591,7 @@ Qed.
Lemma add_mod_idemp_r : forall a b n, n~=0 ->
(a+(b mod n)) mod n == (a+b) mod n.
Proof.
- intros. rewrite !(add_comm a). now apply add_mod_idemp_l.
+ intros a b n **. rewrite !(add_comm a). now apply add_mod_idemp_l.
Qed.
Theorem add_mod: forall a b n, n~=0 ->
diff --git a/theories/Numbers/Integer/Abstract/ZDivTrunc.v b/theories/Numbers/Integer/Abstract/ZDivTrunc.v
index 4915d69c5b..7d374bd4be 100644
--- a/theories/Numbers/Integer/Abstract/ZDivTrunc.v
+++ b/theories/Numbers/Integer/Abstract/ZDivTrunc.v
@@ -69,7 +69,7 @@ Proof. intros. now rewrite rem_opp_r, rem_opp_l. Qed.
Lemma quot_opp_l : forall a b, b ~= 0 -> (-a)÷b == -(a÷b).
Proof.
-intros.
+intros a b ?.
rewrite <- (mul_cancel_l _ _ b) by trivial.
rewrite <- (add_cancel_r _ _ ((-a) rem b)).
now rewrite <- quot_rem, rem_opp_l, mul_opp_r, <- opp_add_distr, <- quot_rem.
@@ -77,7 +77,7 @@ Qed.
Lemma quot_opp_r : forall a b, b ~= 0 -> a÷(-b) == -(a÷b).
Proof.
-intros.
+intros a b ?.
assert (-b ~= 0) by (now rewrite eq_opp_l, opp_0).
rewrite <- (mul_cancel_l _ _ (-b)) by trivial.
rewrite <- (add_cancel_r _ _ (a rem (-b))).
@@ -105,17 +105,17 @@ Qed.
Theorem quot_unique:
forall a b q r, 0<=a -> 0<=r<b -> a == b*q + r -> q == a÷b.
-Proof. intros; now apply NZQuot.div_unique with r. Qed.
+Proof. intros a b q r **; now apply NZQuot.div_unique with r. Qed.
Theorem rem_unique:
forall a b q r, 0<=a -> 0<=r<b -> a == b*q + r -> r == a rem b.
-Proof. intros; now apply NZQuot.mod_unique with q. Qed.
+Proof. intros a b q r **; now apply NZQuot.mod_unique with q. Qed.
(** A division by itself returns 1 *)
Lemma quot_same : forall a, a~=0 -> a÷a == 1.
Proof.
-intros. pos_or_neg a. apply NZQuot.div_same; order.
+intros a ?. pos_or_neg a. apply NZQuot.div_same; order.
rewrite <- quot_opp_opp by trivial. now apply NZQuot.div_same.
Qed.
@@ -138,7 +138,7 @@ Proof. exact NZQuot.mod_small. Qed.
Lemma quot_0_l: forall a, a~=0 -> 0÷a == 0.
Proof.
-intros. pos_or_neg a. apply NZQuot.div_0_l; order.
+intros a ?. pos_or_neg a. apply NZQuot.div_0_l; order.
rewrite <- quot_opp_opp, opp_0 by trivial. now apply NZQuot.div_0_l.
Qed.
@@ -149,7 +149,7 @@ Qed.
Lemma quot_1_r: forall a, a÷1 == a.
Proof.
-intros. pos_or_neg a. now apply NZQuot.div_1_r.
+intros a. pos_or_neg a. now apply NZQuot.div_1_r.
apply opp_inj. rewrite <- quot_opp_l. apply NZQuot.div_1_r; order.
intro EQ; symmetry in EQ; revert EQ; apply lt_neq, lt_0_1.
Qed.
@@ -168,7 +168,7 @@ Proof. exact NZQuot.mod_1_l. Qed.
Lemma quot_mul : forall a b, b~=0 -> (a*b)÷b == a.
Proof.
-intros. pos_or_neg a; pos_or_neg b. apply NZQuot.div_mul; order.
+intros a b ?. pos_or_neg a; pos_or_neg b. apply NZQuot.div_mul; order.
rewrite <- quot_opp_opp, <- mul_opp_r by order. apply NZQuot.div_mul; order.
rewrite <- opp_inj_wd, <- quot_opp_l, <- mul_opp_l by order.
apply NZQuot.div_mul; order.
@@ -190,7 +190,7 @@ Qed.
Lemma rem_nonneg : forall a b, b~=0 -> 0 <= a -> 0 <= a rem b.
Proof.
- intros. pos_or_neg b. destruct (rem_bound_pos a b); order.
+ intros a b **. pos_or_neg b. destruct (rem_bound_pos a b); order.
rewrite <- rem_opp_r; trivial.
destruct (rem_bound_pos a (-b)); trivial.
Qed.
@@ -309,7 +309,7 @@ Proof. exact NZQuot.div_str_pos. Qed.
Lemma quot_small_iff : forall a b, b~=0 -> (a÷b==0 <-> abs a < abs b).
Proof.
-intros. pos_or_neg a; pos_or_neg b.
+intros a b ?. pos_or_neg a; pos_or_neg b.
rewrite NZQuot.div_small_iff; try order. rewrite 2 abs_eq; intuition; order.
rewrite <- opp_inj_wd, opp_0, <- quot_opp_r, NZQuot.div_small_iff by order.
rewrite (abs_eq a), (abs_neq' b); intuition; order.
@@ -321,7 +321,7 @@ Qed.
Lemma rem_small_iff : forall a b, b~=0 -> (a rem b == a <-> abs a < abs b).
Proof.
-intros. rewrite rem_eq, <- quot_small_iff by order.
+intros a b ?. rewrite rem_eq, <- quot_small_iff by order.
rewrite sub_move_r, <- (add_0_r a) at 1. rewrite add_cancel_l.
rewrite eq_sym_iff, eq_mul_0. tauto.
Qed.
@@ -336,7 +336,7 @@ Proof. exact NZQuot.div_lt. Qed.
Lemma quot_le_mono : forall a b c, 0<c -> a<=b -> a÷c <= b÷c.
Proof.
-intros. pos_or_neg a. apply NZQuot.div_le_mono; auto.
+intros a b c **. pos_or_neg a. apply NZQuot.div_le_mono; auto.
pos_or_neg b. apply le_trans with 0.
rewrite <- opp_nonneg_nonpos, <- quot_opp_l by order.
apply quot_pos; order.
@@ -350,7 +350,7 @@ Qed.
Lemma mul_quot_le : forall a b, 0<=a -> b~=0 -> 0 <= b*(a÷b) <= a.
Proof.
-intros. pos_or_neg b.
+intros a b **. pos_or_neg b.
split.
apply mul_nonneg_nonneg; [|apply quot_pos]; order.
apply NZQuot.mul_div_le; order.
@@ -362,7 +362,7 @@ Qed.
Lemma mul_quot_ge : forall a b, a<=0 -> b~=0 -> a <= b*(a÷b) <= 0.
Proof.
-intros.
+intros a b **.
rewrite <- opp_nonneg_nonpos, opp_le_mono, <-mul_opp_r, <-quot_opp_l by order.
rewrite <- opp_nonneg_nonpos in *.
destruct (mul_quot_le (-a) b); tauto.
@@ -415,7 +415,7 @@ Proof. exact NZQuot.div_lt_upper_bound. Qed.
Theorem quot_le_upper_bound:
forall a b q, 0<b -> a <= b*q -> a÷b <= q.
Proof.
-intros.
+intros a b q **.
rewrite <- (quot_mul q b) by order.
apply quot_le_mono; trivial. now rewrite mul_comm.
Qed.
@@ -423,7 +423,7 @@ Qed.
Theorem quot_le_lower_bound:
forall a b q, 0<b -> b*q <= a -> q <= a÷b.
Proof.
-intros.
+intros a b q **.
rewrite <- (quot_mul q b) by order.
apply quot_le_mono; trivial. now rewrite mul_comm.
Qed.
@@ -443,7 +443,7 @@ Lemma rem_add : forall a b c, c~=0 -> 0 <= (a+b*c)*a ->
(a + b * c) rem c == a rem c.
Proof.
assert (forall a b c, c~=0 -> 0<=a -> 0<=a+b*c -> (a+b*c) rem c == a rem c).
- intros. pos_or_neg c. apply NZQuot.mod_add; order.
+ intros a b c **. pos_or_neg c. apply NZQuot.mod_add; order.
rewrite <- (rem_opp_r a), <- (rem_opp_r (a+b*c)) by order.
rewrite <- mul_opp_opp in *.
apply NZQuot.mod_add; order.
@@ -457,7 +457,7 @@ Qed.
Lemma quot_add : forall a b c, c~=0 -> 0 <= (a+b*c)*a ->
(a + b * c) ÷ c == a ÷ c + b.
Proof.
-intros.
+intros a b c **.
rewrite <- (mul_cancel_l _ _ c) by trivial.
rewrite <- (add_cancel_r _ _ ((a+b*c) rem c)).
rewrite <- quot_rem, rem_add by trivial.
@@ -476,14 +476,14 @@ Lemma quot_mul_cancel_r : forall a b c, b~=0 -> c~=0 ->
(a*c)÷(b*c) == a÷b.
Proof.
assert (Aux1 : forall a b c, 0<=a -> 0<b -> c~=0 -> (a*c)÷(b*c) == a÷b).
- intros. pos_or_neg c. apply NZQuot.div_mul_cancel_r; order.
+ intros a b c **. pos_or_neg c. apply NZQuot.div_mul_cancel_r; order.
rewrite <- quot_opp_opp, <- 2 mul_opp_r. apply NZQuot.div_mul_cancel_r; order.
rewrite <- neq_mul_0; intuition order.
assert (Aux2 : forall a b c, 0<=a -> b~=0 -> c~=0 -> (a*c)÷(b*c) == a÷b).
- intros. pos_or_neg b. apply Aux1; order.
+ intros a b c **. pos_or_neg b. apply Aux1; order.
apply opp_inj. rewrite <- 2 quot_opp_r, <- mul_opp_l; try order. apply Aux1; order.
rewrite <- neq_mul_0; intuition order.
-intros. pos_or_neg a. apply Aux2; order.
+intros a b c **. pos_or_neg a. apply Aux2; order.
apply opp_inj. rewrite <- 2 quot_opp_l, <- mul_opp_l; try order. apply Aux2; order.
rewrite <- neq_mul_0; intuition order.
Qed.
@@ -491,13 +491,13 @@ Qed.
Lemma quot_mul_cancel_l : forall a b c, b~=0 -> c~=0 ->
(c*a)÷(c*b) == a÷b.
Proof.
-intros. rewrite !(mul_comm c); now apply quot_mul_cancel_r.
+intros a b c **. rewrite !(mul_comm c); now apply quot_mul_cancel_r.
Qed.
Lemma mul_rem_distr_r: forall a b c, b~=0 -> c~=0 ->
(a*c) rem (b*c) == (a rem b) * c.
Proof.
-intros.
+intros a b c **.
assert (b*c ~= 0) by (rewrite <- neq_mul_0; tauto).
rewrite ! rem_eq by trivial.
rewrite quot_mul_cancel_r by order.
@@ -507,7 +507,7 @@ Qed.
Lemma mul_rem_distr_l: forall a b c, b~=0 -> c~=0 ->
(c*a) rem (c*b) == c * (a rem b).
Proof.
-intros; rewrite !(mul_comm c); now apply mul_rem_distr_r.
+intros a b c **; rewrite !(mul_comm c); now apply mul_rem_distr_r.
Qed.
(** Operations modulo. *)
@@ -515,7 +515,7 @@ Qed.
Theorem rem_rem: forall a n, n~=0 ->
(a rem n) rem n == a rem n.
Proof.
-intros. pos_or_neg a; pos_or_neg n. apply NZQuot.mod_mod; order.
+intros a n **. pos_or_neg a; pos_or_neg n. apply NZQuot.mod_mod; order.
rewrite <- ! (rem_opp_r _ n) by trivial. apply NZQuot.mod_mod; order.
apply opp_inj. rewrite <- !rem_opp_l by order. apply NZQuot.mod_mod; order.
apply opp_inj. rewrite <- !rem_opp_opp by order. apply NZQuot.mod_mod; order.
@@ -526,11 +526,11 @@ Lemma mul_rem_idemp_l : forall a b n, n~=0 ->
Proof.
assert (Aux1 : forall a b n, 0<=a -> 0<=b -> n~=0 ->
((a rem n)*b) rem n == (a*b) rem n).
- intros. pos_or_neg n. apply NZQuot.mul_mod_idemp_l; order.
+ intros a b n **. pos_or_neg n. apply NZQuot.mul_mod_idemp_l; order.
rewrite <- ! (rem_opp_r _ n) by order. apply NZQuot.mul_mod_idemp_l; order.
assert (Aux2 : forall a b n, 0<=a -> n~=0 ->
((a rem n)*b) rem n == (a*b) rem n).
- intros. pos_or_neg b. now apply Aux1.
+ intros a b n **. pos_or_neg b. now apply Aux1.
apply opp_inj. rewrite <-2 rem_opp_l, <-2 mul_opp_r by order.
apply Aux1; order.
intros a b n Hn. pos_or_neg a. now apply Aux2.
@@ -541,7 +541,7 @@ Qed.
Lemma mul_rem_idemp_r : forall a b n, n~=0 ->
(a*(b rem n)) rem n == (a*b) rem n.
Proof.
-intros. rewrite !(mul_comm a). now apply mul_rem_idemp_l.
+intros a b n **. rewrite !(mul_comm a). now apply mul_rem_idemp_l.
Qed.
Theorem mul_rem: forall a b n, n~=0 ->
@@ -564,7 +564,7 @@ Lemma add_rem_idemp_l : forall a b n, n~=0 -> 0 <= a*b ->
Proof.
assert (Aux : forall a b n, 0<=a -> 0<=b -> n~=0 ->
((a rem n)+b) rem n == (a+b) rem n).
- intros. pos_or_neg n. apply NZQuot.add_mod_idemp_l; order.
+ intros a b n **. pos_or_neg n. apply NZQuot.add_mod_idemp_l; order.
rewrite <- ! (rem_opp_r _ n) by order. apply NZQuot.add_mod_idemp_l; order.
intros a b n Hn Hab. destruct (le_0_mul _ _ Hab) as [(Ha,Hb)|(Ha,Hb)].
now apply Aux.
@@ -576,7 +576,7 @@ Qed.
Lemma add_rem_idemp_r : forall a b n, n~=0 -> 0 <= a*b ->
(a+(b rem n)) rem n == (a+b) rem n.
Proof.
-intros. rewrite !(add_comm a). apply add_rem_idemp_l; trivial.
+intros a b n **. rewrite !(add_comm a). apply add_rem_idemp_l; trivial.
now rewrite mul_comm.
Qed.
@@ -598,16 +598,16 @@ Lemma quot_quot : forall a b c, b~=0 -> c~=0 ->
(a÷b)÷c == a÷(b*c).
Proof.
assert (Aux1 : forall a b c, 0<=a -> 0<b -> c~=0 -> (a÷b)÷c == a÷(b*c)).
- intros. pos_or_neg c. apply NZQuot.div_div; order.
+ intros a b c **. pos_or_neg c. apply NZQuot.div_div; order.
apply opp_inj. rewrite <- 2 quot_opp_r, <- mul_opp_r; trivial.
apply NZQuot.div_div; order.
rewrite <- neq_mul_0; intuition order.
assert (Aux2 : forall a b c, 0<=a -> b~=0 -> c~=0 -> (a÷b)÷c == a÷(b*c)).
- intros. pos_or_neg b. apply Aux1; order.
+ intros a b c **. pos_or_neg b. apply Aux1; order.
apply opp_inj. rewrite <- quot_opp_l, <- 2 quot_opp_r, <- mul_opp_l; trivial.
apply Aux1; trivial.
rewrite <- neq_mul_0; intuition order.
-intros. pos_or_neg a. apply Aux2; order.
+intros a b c **. pos_or_neg a. apply Aux2; order.
apply opp_inj. rewrite <- 3 quot_opp_l; try order. apply Aux2; order.
rewrite <- neq_mul_0. tauto.
Qed.
diff --git a/theories/Numbers/Integer/Abstract/ZGcd.v b/theories/Numbers/Integer/Abstract/ZGcd.v
index 09d28a18ec..755557ff17 100644
--- a/theories/Numbers/Integer/Abstract/ZGcd.v
+++ b/theories/Numbers/Integer/Abstract/ZGcd.v
@@ -98,7 +98,7 @@ Qed.
Lemma gcd_abs_l : forall n m, gcd (abs n) m == gcd n m.
Proof.
- intros. destruct (abs_eq_or_opp n) as [H|H]; rewrite H.
+ intros n m. destruct (abs_eq_or_opp n) as [H|H]; rewrite H.
easy. apply gcd_opp_l.
Qed.
@@ -125,7 +125,7 @@ Qed.
Lemma gcd_add_mult_diag_r : forall n m p, gcd n (m+p*n) == gcd n m.
Proof.
- intros. apply gcd_unique_alt; try apply gcd_nonneg.
+ intros n m p. apply gcd_unique_alt; try apply gcd_nonneg.
intros. rewrite gcd_divide_iff. split; intros (U,V); split; trivial.
apply divide_add_r; trivial. now apply divide_mul_r.
apply divide_add_cancel_r with (p*n); trivial.
@@ -164,12 +164,12 @@ Proof.
(* First, a version restricted to natural numbers *)
assert (aux : forall n, 0<=n -> forall m, 0<=m -> Bezout n m (gcd n m)).
intros n Hn; pattern n.
- apply strong_right_induction with (z:=0); trivial.
+ apply (fun H => strong_right_induction _ H 0); trivial.
unfold Bezout. solve_proper.
clear n Hn. intros n Hn IHn.
apply le_lteq in Hn; destruct Hn as [Hn|Hn].
intros m Hm; pattern m.
- apply strong_right_induction with (z:=0); trivial.
+ apply (fun H => strong_right_induction _ H 0); trivial.
unfold Bezout. solve_proper.
clear m Hm. intros m Hm IHm.
destruct (lt_trichotomy n m) as [LT|[EQ|LT]].
@@ -227,7 +227,7 @@ Qed.
Lemma gcd_mul_mono_l_nonneg :
forall n m p, 0<=p -> gcd (p*n) (p*m) == p * gcd n m.
Proof.
- intros. rewrite <- (abs_eq p) at 3; trivial. apply gcd_mul_mono_l.
+ intros n m p ?. rewrite <- (abs_eq p) at 3; trivial. apply gcd_mul_mono_l.
Qed.
Lemma gcd_mul_mono_r :
@@ -239,7 +239,7 @@ Qed.
Lemma gcd_mul_mono_r_nonneg :
forall n m p, 0<=p -> gcd (n*p) (m*p) == gcd n m * p.
Proof.
- intros. rewrite <- (abs_eq p) at 3; trivial. apply gcd_mul_mono_r.
+ intros n m p ?. rewrite <- (abs_eq p) at 3; trivial. apply gcd_mul_mono_r.
Qed.
Lemma gauss : forall n m p, (n | m * p) -> gcd n m == 1 -> (n | p).
diff --git a/theories/Numbers/Integer/Abstract/ZLcm.v b/theories/Numbers/Integer/Abstract/ZLcm.v
index 6aa828ebfc..c45ea12868 100644
--- a/theories/Numbers/Integer/Abstract/ZLcm.v
+++ b/theories/Numbers/Integer/Abstract/ZLcm.v
@@ -33,14 +33,14 @@ Module Type ZLcmProp
Lemma quot_div_nonneg : forall a b, 0<=a -> 0<b -> a÷b == a/b.
Proof.
- intros. apply div_unique_pos with (a rem b).
+ intros a b **. apply div_unique_pos with (a rem b).
now apply rem_bound_pos.
apply quot_rem. order.
Qed.
Lemma rem_mod_nonneg : forall a b, 0<=a -> 0<b -> a rem b == a mod b.
Proof.
- intros. apply mod_unique_pos with (a÷b).
+ intros a b **. apply mod_unique_pos with (a÷b).
now apply rem_bound_pos.
apply quot_rem. order.
Qed.
@@ -290,7 +290,7 @@ Qed.
Lemma lcm_divide_iff : forall n m p,
(lcm n m | p) <-> (n | p) /\ (m | p).
Proof.
- intros. split. split.
+ intros n m p. split. split.
transitivity (lcm n m); trivial using divide_lcm_l.
transitivity (lcm n m); trivial using divide_lcm_r.
intros (H,H'). now apply lcm_least.
@@ -387,7 +387,7 @@ Qed.
Lemma lcm_abs_l : forall n m, lcm (abs n) m == lcm n m.
Proof.
- intros. destruct (abs_eq_or_opp n) as [H|H]; rewrite H.
+ intros n m. destruct (abs_eq_or_opp n) as [H|H]; rewrite H.
easy. apply lcm_opp_l.
Qed.
@@ -438,7 +438,7 @@ Qed.
Lemma lcm_mul_mono_l_nonneg :
forall n m p, 0<=p -> lcm (p*n) (p*m) == p * lcm n m.
Proof.
- intros. rewrite <- (abs_eq p) at 3; trivial. apply lcm_mul_mono_l.
+ intros n m p ?. rewrite <- (abs_eq p) at 3; trivial. apply lcm_mul_mono_l.
Qed.
Lemma lcm_mul_mono_r :
@@ -450,7 +450,7 @@ Qed.
Lemma lcm_mul_mono_r_nonneg :
forall n m p, 0<=p -> lcm (n*p) (m*p) == lcm n m * p.
Proof.
- intros. rewrite <- (abs_eq p) at 3; trivial. apply lcm_mul_mono_r.
+ intros n m p ?. rewrite <- (abs_eq p) at 3; trivial. apply lcm_mul_mono_r.
Qed.
Lemma gcd_1_lcm_mul : forall n m, n~=0 -> m~=0 ->
diff --git a/theories/Numbers/Integer/Abstract/ZMaxMin.v b/theories/Numbers/Integer/Abstract/ZMaxMin.v
index ed0b0c69a0..4af24b7754 100644
--- a/theories/Numbers/Integer/Abstract/ZMaxMin.v
+++ b/theories/Numbers/Integer/Abstract/ZMaxMin.v
@@ -20,133 +20,133 @@ Include ZMulOrderProp Z.
(** Succ *)
-Lemma succ_max_distr : forall n m, S (max n m) == max (S n) (S m).
+Lemma succ_max_distr n m : S (max n m) == max (S n) (S m).
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; now rewrite <- ?succ_le_mono.
Qed.
-Lemma succ_min_distr : forall n m, S (min n m) == min (S n) (S m).
+Lemma succ_min_distr n m : S (min n m) == min (S n) (S m).
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; now rewrite <- ?succ_le_mono.
Qed.
(** Pred *)
-Lemma pred_max_distr : forall n m, P (max n m) == max (P n) (P m).
+Lemma pred_max_distr n m : P (max n m) == max (P n) (P m).
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; now rewrite <- ?pred_le_mono.
Qed.
-Lemma pred_min_distr : forall n m, P (min n m) == min (P n) (P m).
+Lemma pred_min_distr n m : P (min n m) == min (P n) (P m).
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; now rewrite <- ?pred_le_mono.
Qed.
(** Add *)
-Lemma add_max_distr_l : forall n m p, max (p + n) (p + m) == p + max n m.
+Lemma add_max_distr_l n m p : max (p + n) (p + m) == p + max n m.
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; now rewrite <- ?add_le_mono_l.
Qed.
-Lemma add_max_distr_r : forall n m p, max (n + p) (m + p) == max n m + p.
+Lemma add_max_distr_r n m p : max (n + p) (m + p) == max n m + p.
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; now rewrite <- ?add_le_mono_r.
Qed.
-Lemma add_min_distr_l : forall n m p, min (p + n) (p + m) == p + min n m.
+Lemma add_min_distr_l n m p : min (p + n) (p + m) == p + min n m.
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; now rewrite <- ?add_le_mono_l.
Qed.
-Lemma add_min_distr_r : forall n m p, min (n + p) (m + p) == min n m + p.
+Lemma add_min_distr_r n m p : min (n + p) (m + p) == min n m + p.
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; now rewrite <- ?add_le_mono_r.
Qed.
(** Opp *)
-Lemma opp_max_distr : forall n m, -(max n m) == min (-n) (-m).
+Lemma opp_max_distr n m : -(max n m) == min (-n) (-m).
Proof.
- intros. destruct (le_ge_cases n m).
+ destruct (le_ge_cases n m).
rewrite max_r by trivial. symmetry. apply min_r. now rewrite <- opp_le_mono.
rewrite max_l by trivial. symmetry. apply min_l. now rewrite <- opp_le_mono.
Qed.
-Lemma opp_min_distr : forall n m, -(min n m) == max (-n) (-m).
+Lemma opp_min_distr n m : -(min n m) == max (-n) (-m).
Proof.
- intros. destruct (le_ge_cases n m).
+ destruct (le_ge_cases n m).
rewrite min_l by trivial. symmetry. apply max_l. now rewrite <- opp_le_mono.
rewrite min_r by trivial. symmetry. apply max_r. now rewrite <- opp_le_mono.
Qed.
(** Sub *)
-Lemma sub_max_distr_l : forall n m p, max (p - n) (p - m) == p - min n m.
+Lemma sub_max_distr_l n m p : max (p - n) (p - m) == p - min n m.
Proof.
- intros. destruct (le_ge_cases n m).
+ destruct (le_ge_cases n m).
rewrite min_l by trivial. apply max_l. now rewrite <- sub_le_mono_l.
rewrite min_r by trivial. apply max_r. now rewrite <- sub_le_mono_l.
Qed.
-Lemma sub_max_distr_r : forall n m p, max (n - p) (m - p) == max n m - p.
+Lemma sub_max_distr_r n m p : max (n - p) (m - p) == max n m - p.
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; try order; now apply sub_le_mono_r.
Qed.
-Lemma sub_min_distr_l : forall n m p, min (p - n) (p - m) == p - max n m.
+Lemma sub_min_distr_l n m p : min (p - n) (p - m) == p - max n m.
Proof.
- intros. destruct (le_ge_cases n m).
+ destruct (le_ge_cases n m).
rewrite max_r by trivial. apply min_r. now rewrite <- sub_le_mono_l.
rewrite max_l by trivial. apply min_l. now rewrite <- sub_le_mono_l.
Qed.
-Lemma sub_min_distr_r : forall n m p, min (n - p) (m - p) == min n m - p.
+Lemma sub_min_distr_r n m p : min (n - p) (m - p) == min n m - p.
Proof.
- intros. destruct (le_ge_cases n m);
+ destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; try order; now apply sub_le_mono_r.
Qed.
(** Mul *)
-Lemma mul_max_distr_nonneg_l : forall n m p, 0 <= p ->
+Lemma mul_max_distr_nonneg_l n m p : 0 <= p ->
max (p * n) (p * m) == p * max n m.
Proof.
intros. destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; try order; now apply mul_le_mono_nonneg_l.
Qed.
-Lemma mul_max_distr_nonneg_r : forall n m p, 0 <= p ->
+Lemma mul_max_distr_nonneg_r n m p : 0 <= p ->
max (n * p) (m * p) == max n m * p.
Proof.
intros. destruct (le_ge_cases n m);
[rewrite 2 max_r | rewrite 2 max_l]; try order; now apply mul_le_mono_nonneg_r.
Qed.
-Lemma mul_min_distr_nonneg_l : forall n m p, 0 <= p ->
+Lemma mul_min_distr_nonneg_l n m p : 0 <= p ->
min (p * n) (p * m) == p * min n m.
Proof.
intros. destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; try order; now apply mul_le_mono_nonneg_l.
Qed.
-Lemma mul_min_distr_nonneg_r : forall n m p, 0 <= p ->
+Lemma mul_min_distr_nonneg_r n m p : 0 <= p ->
min (n * p) (m * p) == min n m * p.
Proof.
intros. destruct (le_ge_cases n m);
[rewrite 2 min_l | rewrite 2 min_r]; try order; now apply mul_le_mono_nonneg_r.
Qed.
-Lemma mul_max_distr_nonpos_l : forall n m p, p <= 0 ->
+Lemma mul_max_distr_nonpos_l n m p : p <= 0 ->
max (p * n) (p * m) == p * min n m.
Proof.
intros. destruct (le_ge_cases n m).
@@ -154,7 +154,7 @@ Proof.
rewrite min_r by trivial. rewrite max_r. reflexivity. now apply mul_le_mono_nonpos_l.
Qed.
-Lemma mul_max_distr_nonpos_r : forall n m p, p <= 0 ->
+Lemma mul_max_distr_nonpos_r n m p : p <= 0 ->
max (n * p) (m * p) == min n m * p.
Proof.
intros. destruct (le_ge_cases n m).
@@ -162,7 +162,7 @@ Proof.
rewrite min_r by trivial. rewrite max_r. reflexivity. now apply mul_le_mono_nonpos_r.
Qed.
-Lemma mul_min_distr_nonpos_l : forall n m p, p <= 0 ->
+Lemma mul_min_distr_nonpos_l n m p : p <= 0 ->
min (p * n) (p * m) == p * max n m.
Proof.
intros. destruct (le_ge_cases n m).
@@ -170,7 +170,7 @@ Proof.
rewrite max_l by trivial. rewrite min_l. reflexivity. now apply mul_le_mono_nonpos_l.
Qed.
-Lemma mul_min_distr_nonpos_r : forall n m p, p <= 0 ->
+Lemma mul_min_distr_nonpos_r n m p : p <= 0 ->
min (n * p) (m * p) == max n m * p.
Proof.
intros. destruct (le_ge_cases n m).
diff --git a/theories/Numbers/Integer/Abstract/ZMulOrder.v b/theories/Numbers/Integer/Abstract/ZMulOrder.v
index 7d97d11818..0275a5fa65 100644
--- a/theories/Numbers/Integer/Abstract/ZMulOrder.v
+++ b/theories/Numbers/Integer/Abstract/ZMulOrder.v
@@ -167,7 +167,7 @@ Qed.
Theorem eq_mul_1 : forall n m, n * m == 1 -> n == 1 \/ n == -1.
Proof.
assert (F := lt_m1_0).
-zero_pos_neg n.
+intro n; zero_pos_neg n.
(* n = 0 *)
intros m. nzsimpl. now left.
(* 0 < n, proving P n /\ P (-n) *)
@@ -205,7 +205,7 @@ Qed.
Theorem lt_mul_r : forall n m p, 0 < n -> 1 < p -> n < m -> n < m * p.
Proof.
-intros. stepl (n * 1) by now rewrite mul_1_r.
+intros n m p **. stepl (n * 1) by now rewrite mul_1_r.
apply mul_lt_mono_nonneg.
now apply lt_le_incl. assumption. apply le_0_1. assumption.
Qed.
diff --git a/theories/Numbers/Integer/Abstract/ZParity.v b/theories/Numbers/Integer/Abstract/ZParity.v
index 4b61b18479..0f68278cf0 100644
--- a/theories/Numbers/Integer/Abstract/ZParity.v
+++ b/theories/Numbers/Integer/Abstract/ZParity.v
@@ -19,19 +19,19 @@ Include NZParityProp Z Z ZP.
Lemma odd_pred : forall n, odd (P n) = even n.
Proof.
- intros. rewrite <- (succ_pred n) at 2. symmetry. apply even_succ.
+ intros n. rewrite <- (succ_pred n) at 2. symmetry. apply even_succ.
Qed.
Lemma even_pred : forall n, even (P n) = odd n.
Proof.
- intros. rewrite <- (succ_pred n) at 2. symmetry. apply odd_succ.
+ intros n. rewrite <- (succ_pred n) at 2. symmetry. apply odd_succ.
Qed.
Lemma even_opp : forall n, even (-n) = even n.
Proof.
assert (H : forall n, Even n -> Even (-n)).
intros n (m,H). exists (-m). rewrite mul_opp_r. now f_equiv.
- intros. rewrite eq_iff_eq_true, !even_spec.
+ intros n. rewrite eq_iff_eq_true, !even_spec.
split. rewrite <- (opp_involutive n) at 2. apply H.
apply H.
Qed.
diff --git a/theories/Numbers/Integer/Abstract/ZPow.v b/theories/Numbers/Integer/Abstract/ZPow.v
index bec77fd136..9557212a86 100644
--- a/theories/Numbers/Integer/Abstract/ZPow.v
+++ b/theories/Numbers/Integer/Abstract/ZPow.v
@@ -73,7 +73,7 @@ Qed.
Lemma pow_even_abs : forall a b, Even b -> a^b == (abs a)^b.
Proof.
- intros. destruct (abs_eq_or_opp a) as [EQ|EQ]; rewrite EQ.
+ intros a b ?. destruct (abs_eq_or_opp a) as [EQ|EQ]; rewrite EQ.
reflexivity.
symmetry. now apply pow_opp_even.
Qed.
@@ -119,7 +119,7 @@ Qed.
Lemma abs_pow : forall a b, abs (a^b) == (abs a)^b.
Proof.
intros a b.
- destruct (Even_or_Odd b).
+ destruct (Even_or_Odd b) as [H|H].
rewrite pow_even_abs by trivial.
apply abs_eq, pow_nonneg, abs_nonneg.
rewrite pow_odd_abs_sgn by trivial.
diff --git a/theories/Numbers/Integer/Abstract/ZSgnAbs.v b/theories/Numbers/Integer/Abstract/ZSgnAbs.v
index 03e0c0345d..3ebbec9397 100644
--- a/theories/Numbers/Integer/Abstract/ZSgnAbs.v
+++ b/theories/Numbers/Integer/Abstract/ZSgnAbs.v
@@ -40,11 +40,11 @@ Module Type GenericSgn (Import Z : ZDecAxiomsSig')
(Import ZP : ZMulOrderProp Z) <: HasSgn Z.
Definition sgn n :=
match compare 0 n with Eq => 0 | Lt => 1 | Gt => -1 end.
- Lemma sgn_null : forall n, n==0 -> sgn n == 0.
+ Lemma sgn_null n : n==0 -> sgn n == 0.
Proof. unfold sgn; intros. destruct (compare_spec 0 n); order. Qed.
- Lemma sgn_pos : forall n, 0<n -> sgn n == 1.
+ Lemma sgn_pos n : 0<n -> sgn n == 1.
Proof. unfold sgn; intros. destruct (compare_spec 0 n); order. Qed.
- Lemma sgn_neg : forall n, n<0 -> sgn n == -1.
+ Lemma sgn_neg n : n<0 -> sgn n == -1.
Proof. unfold sgn; intros. destruct (compare_spec 0 n); order. Qed.
End GenericSgn.
@@ -101,7 +101,7 @@ Qed.
Lemma abs_opp : forall n, abs (-n) == abs n.
Proof.
- intros. destruct_max n.
+ intros n. destruct_max n.
rewrite (abs_neq (-n)), opp_involutive. reflexivity.
now rewrite opp_nonpos_nonneg.
rewrite (abs_eq (-n)). reflexivity.
@@ -115,14 +115,14 @@ Qed.
Lemma abs_0_iff : forall n, abs n == 0 <-> n==0.
Proof.
- split. destruct_max n; auto.
+ intros n; split. destruct_max n; auto.
now rewrite eq_opp_l, opp_0.
intros EQ; rewrite EQ. rewrite abs_eq; auto using eq_refl, le_refl.
Qed.
Lemma abs_pos : forall n, 0 < abs n <-> n~=0.
Proof.
- intros. rewrite <- abs_0_iff. split; [intros LT| intros NEQ].
+ intros n. rewrite <- abs_0_iff. split; [intros LT| intros NEQ].
intro EQ. rewrite EQ in LT. now elim (lt_irrefl 0).
assert (LE : 0 <= abs n) by apply abs_nonneg.
rewrite lt_eq_cases in LE; destruct LE; auto.
@@ -131,12 +131,12 @@ Qed.
Lemma abs_eq_or_opp : forall n, abs n == n \/ abs n == -n.
Proof.
- intros. destruct_max n; auto with relations.
+ intros n. destruct_max n; auto with relations.
Qed.
Lemma abs_or_opp_abs : forall n, n == abs n \/ n == - abs n.
Proof.
- intros. destruct_max n; rewrite ? opp_involutive; auto with relations.
+ intros n. destruct_max n; rewrite ? opp_involutive; auto with relations.
Qed.
Lemma abs_involutive : forall n, abs (abs n) == abs n.
@@ -147,7 +147,7 @@ Qed.
Lemma abs_spec : forall n,
(0 <= n /\ abs n == n) \/ (n < 0 /\ abs n == -n).
Proof.
- intros. destruct (le_gt_cases 0 n).
+ intros n. destruct (le_gt_cases 0 n).
left; split; auto. now apply abs_eq.
right; split; auto. apply abs_neq. now apply lt_le_incl.
Qed.
@@ -156,7 +156,7 @@ Lemma abs_case_strong :
forall (P:t->Prop) n, Proper (eq==>iff) P ->
(0<=n -> P n) -> (n<=0 -> P (-n)) -> P (abs n).
Proof.
- intros. destruct_max n; auto.
+ intros P n **. destruct_max n; auto.
Qed.
Lemma abs_case : forall (P:t->Prop) n, Proper (eq==>iff) P ->
@@ -196,7 +196,7 @@ Qed.
Lemma abs_triangle : forall n m, abs (n + m) <= abs n + abs m.
Proof.
- intros. destruct_max n; destruct_max m.
+ intros n m. destruct_max n; destruct_max m.
rewrite abs_eq. apply le_refl. now apply add_nonneg_nonneg.
destruct_max (n+m); try rewrite opp_add_distr;
apply add_le_mono_l || apply add_le_mono_r.
@@ -212,7 +212,7 @@ Qed.
Lemma abs_sub_triangle : forall n m, abs n - abs m <= abs (n-m).
Proof.
- intros.
+ intros n m.
rewrite le_sub_le_add_l, add_comm.
rewrite <- (sub_simpl_r n m) at 1.
apply abs_triangle.
@@ -223,10 +223,10 @@ Qed.
Lemma abs_mul : forall n m, abs (n * m) == abs n * abs m.
Proof.
assert (H : forall n m, 0<=n -> abs (n*m) == n * abs m).
- intros. destruct_max m.
+ intros n m ?. destruct_max m.
rewrite abs_eq. apply eq_refl. now apply mul_nonneg_nonneg.
rewrite abs_neq, mul_opp_r. reflexivity. now apply mul_nonneg_nonpos .
- intros. destruct_max n. now apply H.
+ intros n m. destruct_max n. now apply H.
rewrite <- mul_opp_opp, H, abs_opp. reflexivity.
now apply opp_nonneg_nonpos.
Qed.
@@ -271,7 +271,7 @@ Qed.
Lemma sgn_pos_iff : forall n, sgn n == 1 <-> 0<n.
Proof.
- split; try apply sgn_pos. destruct_sgn n; auto.
+ intros n; split; try apply sgn_pos. destruct_sgn n; auto.
intros. elim (lt_neq 0 1); auto. apply lt_0_1.
intros. elim (lt_neq (-1) 1); auto.
apply lt_trans with 0. rewrite opp_neg_pos. apply lt_0_1. apply lt_0_1.
@@ -279,7 +279,7 @@ Qed.
Lemma sgn_null_iff : forall n, sgn n == 0 <-> n==0.
Proof.
- split; try apply sgn_null. destruct_sgn n; auto with relations.
+ intros n; split; try apply sgn_null. destruct_sgn n; auto with relations.
intros. elim (lt_neq 0 1); auto with relations. apply lt_0_1.
intros. elim (lt_neq (-1) 0); auto.
rewrite opp_neg_pos. apply lt_0_1.
@@ -287,7 +287,7 @@ Qed.
Lemma sgn_neg_iff : forall n, sgn n == -1 <-> n<0.
Proof.
- split; try apply sgn_neg. destruct_sgn n; auto with relations.
+ intros n; split; try apply sgn_neg. destruct_sgn n; auto with relations.
intros. elim (lt_neq (-1) 1); auto with relations.
apply lt_trans with 0. rewrite opp_neg_pos. apply lt_0_1. apply lt_0_1.
intros. elim (lt_neq (-1) 0); auto with relations.
@@ -296,7 +296,7 @@ Qed.
Lemma sgn_opp : forall n, sgn (-n) == - sgn n.
Proof.
- intros. destruct_sgn n.
+ intros n. destruct_sgn n.
apply sgn_neg. now rewrite opp_neg_pos.
setoid_replace n with 0 by auto with relations.
rewrite opp_0. apply sgn_0.
@@ -305,7 +305,7 @@ Qed.
Lemma sgn_nonneg : forall n, 0 <= sgn n <-> 0 <= n.
Proof.
- split.
+ intros n; split.
destruct_sgn n; intros.
now apply lt_le_incl.
order.
@@ -323,7 +323,7 @@ Qed.
Lemma sgn_mul : forall n m, sgn (n*m) == sgn n * sgn m.
Proof.
- intros. destruct_sgn n; nzsimpl.
+ intros n m. destruct_sgn n; nzsimpl.
destruct_sgn m.
apply sgn_pos. now apply mul_pos_pos.
apply sgn_null. rewrite eq_mul_0; auto with relations.
@@ -337,7 +337,7 @@ Qed.
Lemma sgn_abs : forall n, n * sgn n == abs n.
Proof.
- intros. symmetry.
+ intros n. symmetry.
destruct_sgn n; try rewrite mul_opp_r; nzsimpl.
apply abs_eq. now apply lt_le_incl.
rewrite abs_0_iff; auto with relations.
@@ -346,7 +346,7 @@ Qed.
Lemma abs_sgn : forall n, abs n * sgn n == n.
Proof.
- intros.
+ intros n.
destruct_sgn n; try rewrite mul_opp_r; nzsimpl; auto.
apply abs_eq. now apply lt_le_incl.
rewrite eq_opp_l. apply abs_neq. now apply lt_le_incl.
@@ -354,7 +354,7 @@ Qed.
Lemma sgn_sgn : forall x, sgn (sgn x) == sgn x.
Proof.
- intros.
+ intros x.
destruct (sgn_spec x) as [(LT,EQ)|[(EQ',EQ)|(LT,EQ)]]; rewrite EQ.
apply sgn_pos, lt_0_1.
now apply sgn_null.
diff --git a/theories/PArith/BinPosDef.v b/theories/PArith/BinPosDef.v
index b41cd571dc..2ec9f4d871 100644
--- a/theories/PArith/BinPosDef.v
+++ b/theories/PArith/BinPosDef.v
@@ -639,10 +639,10 @@ Fixpoint of_hex_uint (d:Hexadecimal.uint) : N :=
| Hexadecimal.Df l => Npos (of_hex_uint_acc l 1~1~1~1)
end.
-Definition of_num_uint (d:Numeral.uint) : N :=
+Definition of_num_uint (d:Number.uint) : N :=
match d with
- | Numeral.UIntDec d => of_uint d
- | Numeral.UIntHex d => of_hex_uint d
+ | Number.UIntDecimal d => of_uint d
+ | Number.UIntHexadecimal d => of_hex_uint d
end.
Definition of_int (d:Decimal.int) : option positive :=
@@ -665,10 +665,10 @@ Definition of_hex_int (d:Hexadecimal.int) : option positive :=
| Hexadecimal.Neg _ => None
end.
-Definition of_num_int (d:Numeral.int) : option positive :=
+Definition of_num_int (d:Number.int) : option positive :=
match d with
- | Numeral.IntDec d => of_int d
- | Numeral.IntHex d => of_hex_int d
+ | Number.IntDecimal d => of_int d
+ | Number.IntHexadecimal d => of_hex_int d
end.
Fixpoint to_little_uint p :=
@@ -689,13 +689,13 @@ Fixpoint to_little_hex_uint p :=
Definition to_hex_uint p := Hexadecimal.rev (to_little_hex_uint p).
-Definition to_num_uint p := Numeral.UIntDec (to_uint p).
+Definition to_num_uint p := Number.UIntDecimal (to_uint p).
Definition to_int n := Decimal.Pos (to_uint n).
Definition to_hex_int p := Hexadecimal.Pos (to_hex_uint p).
-Definition to_num_int n := Numeral.IntDec (to_int n).
+Definition to_num_int n := Number.IntDecimal (to_int n).
Number Notation positive of_num_int to_num_uint : positive_scope.
diff --git a/theories/QArith/QArith_base.v b/theories/QArith/QArith_base.v
index 192dcd885b..fa4f9134cc 100644
--- a/theories/QArith/QArith_base.v
+++ b/theories/QArith/QArith_base.v
@@ -18,6 +18,9 @@ Require Export Morphisms Setoid Bool.
Record Q : Set := Qmake {Qnum : Z; Qden : positive}.
+Declare Scope hex_Q_scope.
+Delimit Scope hex_Q_scope with xQ.
+
Declare Scope Q_scope.
Delimit Scope Q_scope with Q.
Bind Scope Q_scope with Q.
@@ -33,104 +36,6 @@ Ltac simpl_mult := rewrite ?Pos2Z.inj_mul.
Notation "a # b" := (Qmake a b) (at level 55, no associativity) : Q_scope.
-Definition of_decimal (d:Decimal.decimal) : Q :=
- let '(i, f, e) :=
- match d with
- | Decimal.Decimal i f => (i, f, Decimal.Pos Decimal.Nil)
- | Decimal.DecimalExp i f e => (i, f, e)
- end in
- let num := Z.of_int (Decimal.app_int i f) in
- let e := Z.sub (Z.of_int e) (Z.of_nat (Decimal.nb_digits f)) in
- match e with
- | Z0 => Qmake num 1
- | Zpos e => Qmake (Pos.iter (Z.mul 10) num e) 1
- | Zneg e => Qmake num (Pos.iter (Pos.mul 10) 1%positive e)
- 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 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.
-
-Definition of_hexadecimal (d:Hexadecimal.hexadecimal) : Q :=
- let '(i, f, e) :=
- match d with
- | Hexadecimal.Hexadecimal i f => (i, f, Decimal.Pos Decimal.Nil)
- | Hexadecimal.HexadecimalExp i f e => (i, f, e)
- end in
- let num := Z.of_hex_int (Hexadecimal.app_int i f) in
- let e := Z.sub (Z.of_int e) (Z.mul 4 (Z.of_nat (Hexadecimal.nb_digits f))) in
- match e with
- | Z0 => Qmake num 1
- | Zpos e => Qmake (Pos.iter (Z.mul 2) num e) 1
- | Zneg e => Qmake num (Pos.iter (Pos.mul 2) 1%positive e)
- end.
-
-Definition to_hexadecimal (q:Q) : option Hexadecimal.hexadecimal :=
- let mk_exp i e :=
- Hexadecimal.HexadecimalExp i Hexadecimal.Nil (Z.to_int (Z.opp e)) in
- let num := Z.to_hex_int (Qnum q) in
- let (den, e_den) := Hexadecimal.nztail (Pos.to_hex_uint (Qden q)) in
- let e := Z.of_nat e_den in
- match den with
- | Hexadecimal.D1 Hexadecimal.Nil =>
- match e_den with
- | O => Some (Hexadecimal.Hexadecimal num Hexadecimal.Nil)
- | _ => Some (mk_exp num (4 * e)%Z)
- end
- | Hexadecimal.D2 Hexadecimal.Nil => Some (mk_exp num (1 + 4 * e)%Z)
- | Hexadecimal.D4 Hexadecimal.Nil => Some (mk_exp num (2 + 4 * e)%Z)
- | Hexadecimal.D8 Hexadecimal.Nil => Some (mk_exp num (3 + 4 * e)%Z)
- | _ => None
- end.
-
-Definition of_numeral (d:Numeral.numeral) : option Q :=
- match d with
- | Numeral.Dec d => Some (of_decimal d)
- | Numeral.Hex d => Some (of_hexadecimal d)
- end.
-
-Definition to_numeral (q:Q) : option Numeral.numeral :=
- match to_decimal q with
- | None => None
- | Some q => Some (Numeral.Dec q)
- end.
-
-Number Notation Q of_numeral to_numeral : Q_scope.
-
Definition inject_Z (x : Z) := Qmake x 1.
Arguments inject_Z x%Z.
@@ -316,7 +221,7 @@ Definition Qminus (x y : Q) := Qplus x (Qopp y).
Definition Qinv (x : Q) :=
match Qnum x with
- | Z0 => 0
+ | Z0 => 0#1
| Zpos p => (QDen x)#p
| Zneg p => (Zneg (Qden x))#p
end.
@@ -335,6 +240,188 @@ Register Qminus as rat.Q.Qminus.
Register Qopp as rat.Q.Qopp.
Register Qmult as rat.Q.Qmult.
+(** Number notation for constants *)
+
+Inductive IZ :=
+ | IZpow_pos : Z -> positive -> IZ
+ | IZ0 : IZ
+ | IZpos : positive -> IZ
+ | IZneg : positive -> IZ.
+
+Inductive IQ :=
+ | IQmake : IZ -> positive -> IQ
+ | IQmult : IQ -> IQ -> IQ
+ | IQdiv : IQ -> IQ -> IQ.
+
+Definition IZ_of_Z z :=
+ match z with
+ | Z0 => IZ0
+ | Zpos e => IZpos e
+ | Zneg e => IZneg e
+ end.
+
+Definition IZ_to_Z z :=
+ match z with
+ | IZ0 => Some Z0
+ | IZpos e => Some (Zpos e)
+ | IZneg e => Some (Zneg e)
+ | IZpow_pos _ _ => None
+ end.
+
+Definition of_decimal (d:Decimal.decimal) : IQ :=
+ let '(i, f, e) :=
+ match d with
+ | Decimal.Decimal i f => (i, f, Decimal.Pos Decimal.Nil)
+ | Decimal.DecimalExp i f e => (i, f, e)
+ end in
+ let num := Z.of_int (Decimal.app_int i f) in
+ let den := Nat.iter (Decimal.nb_digits f) (Pos.mul 10) 1%positive in
+ let q := IQmake (IZ_of_Z num) den in
+ let e := Z.of_int e in
+ match e with
+ | Z0 => q
+ | Zpos e => IQmult q (IQmake (IZpow_pos 10 e) 1)
+ | Zneg e => IQdiv q (IQmake (IZpow_pos 10 e) 1)
+ end.
+
+Definition IQmake_to_decimal num den :=
+ let num := Z.to_int num in
+ let (den, e_den) := Decimal.nztail (Pos.to_uint den) in
+ match den with
+ | Decimal.D1 Decimal.Nil =>
+ match e_den with
+ | O => Some (Decimal.Decimal num Decimal.Nil)
+ | ne =>
+ let ai := Decimal.abs num in
+ let ni := Decimal.nb_digits ai in
+ if Nat.ltb ne ni then
+ let i := Decimal.del_tail_int ne num in
+ let f := Decimal.del_head (Nat.sub ni ne) ai in
+ Some (Decimal.Decimal i f)
+ else
+ let z := match num with
+ | Decimal.Pos _ => Decimal.Pos (Decimal.zero)
+ | Decimal.Neg _ => Decimal.Neg (Decimal.zero) end in
+ Some (Decimal.Decimal z (Nat.iter (Nat.sub ne ni) Decimal.D0 ai))
+ end
+ | _ => None
+ end.
+
+Definition IQmake_to_decimal' num den :=
+ match IZ_to_Z num with
+ | None => None
+ | Some num => IQmake_to_decimal num den
+ end.
+
+Definition to_decimal (n : IQ) : option Decimal.decimal :=
+ match n with
+ | IQmake num den => IQmake_to_decimal' num den
+ | IQmult (IQmake num den) (IQmake (IZpow_pos 10 e) 1) =>
+ match IQmake_to_decimal' num den with
+ | Some (Decimal.Decimal i f) =>
+ Some (Decimal.DecimalExp i f (Pos.to_int e))
+ | _ => None
+ end
+ | IQdiv (IQmake num den) (IQmake (IZpow_pos 10 e) 1) =>
+ match IQmake_to_decimal' num den with
+ | Some (Decimal.Decimal i f) =>
+ Some (Decimal.DecimalExp i f (Decimal.Neg (Pos.to_uint e)))
+ | _ => None
+ end
+ | _ => None
+ end.
+
+Definition of_hexadecimal (d:Hexadecimal.hexadecimal) : IQ :=
+ let '(i, f, e) :=
+ match d with
+ | Hexadecimal.Hexadecimal i f => (i, f, Decimal.Pos Decimal.Nil)
+ | Hexadecimal.HexadecimalExp i f e => (i, f, e)
+ end in
+ let num := Z.of_hex_int (Hexadecimal.app_int i f) in
+ let den := Nat.iter (Hexadecimal.nb_digits f) (Pos.mul 16) 1%positive in
+ let q := IQmake (IZ_of_Z num) den in
+ let e := Z.of_int e in
+ match e with
+ | Z0 => q
+ | Zpos e => IQmult q (IQmake (IZpow_pos 2 e) 1)
+ | Zneg e => IQdiv q (IQmake (IZpow_pos 2 e) 1)
+ end.
+
+Definition IQmake_to_hexadecimal num den :=
+ let num := Z.to_hex_int num in
+ let (den, e_den) := Hexadecimal.nztail (Pos.to_hex_uint den) in
+ match den with
+ | Hexadecimal.D1 Hexadecimal.Nil =>
+ match e_den with
+ | O => Some (Hexadecimal.Hexadecimal num Hexadecimal.Nil)
+ | ne =>
+ let ai := Hexadecimal.abs num in
+ let ni := Hexadecimal.nb_digits ai in
+ if Nat.ltb ne ni then
+ let i := Hexadecimal.del_tail_int ne num in
+ let f := Hexadecimal.del_head (Nat.sub ni ne) ai in
+ Some (Hexadecimal.Hexadecimal i f)
+ else
+ let z := match num with
+ | Hexadecimal.Pos _ => Hexadecimal.Pos (Hexadecimal.zero)
+ | Hexadecimal.Neg _ => Hexadecimal.Neg (Hexadecimal.zero) end in
+ Some (Hexadecimal.Hexadecimal z (Nat.iter (Nat.sub ne ni) Hexadecimal.D0 ai))
+ end
+ | _ => None
+ end.
+
+Definition IQmake_to_hexadecimal' num den :=
+ match IZ_to_Z num with
+ | None => None
+ | Some num => IQmake_to_hexadecimal num den
+ end.
+
+Definition to_hexadecimal (n : IQ) : option Hexadecimal.hexadecimal :=
+ match n with
+ | IQmake num den => IQmake_to_hexadecimal' num den
+ | IQmult (IQmake num den) (IQmake (IZpow_pos 2 e) 1) =>
+ match IQmake_to_hexadecimal' num den with
+ | Some (Hexadecimal.Hexadecimal i f) =>
+ Some (Hexadecimal.HexadecimalExp i f (Pos.to_int e))
+ | _ => None
+ end
+ | IQdiv (IQmake num den) (IQmake (IZpow_pos 2 e) 1) =>
+ match IQmake_to_hexadecimal' num den with
+ | Some (Hexadecimal.Hexadecimal i f) =>
+ Some (Hexadecimal.HexadecimalExp i f (Decimal.Neg (Pos.to_uint e)))
+ | _ => None
+ end
+ | _ => None
+ end.
+
+Definition of_number (n : Number.number) : IQ :=
+ match n with
+ | Number.Decimal d => of_decimal d
+ | Number.Hexadecimal h => of_hexadecimal h
+ end.
+
+Definition to_number (q:IQ) : option Number.number :=
+ match to_decimal q with
+ | None => None
+ | Some q => Some (Number.Decimal q)
+ end.
+
+Definition to_hex_number q :=
+ match to_hexadecimal q with
+ | None => None
+ | Some q => Some (Number.Hexadecimal q)
+ end.
+
+Number Notation Q of_number to_hex_number (via IQ
+ mapping [Qmake => IQmake, Qmult => IQmult, Qdiv => IQdiv,
+ Z.pow_pos => IZpow_pos, Z0 => IZ0, Zpos => IZpos, Zneg => IZneg])
+ : hex_Q_scope.
+
+Number Notation Q of_number to_number (via IQ
+ mapping [Qmake => IQmake, Qmult => IQmult, Qdiv => IQdiv,
+ Z.pow_pos => IZpow_pos, Z0 => IZ0, Zpos => IZpos, Zneg => IZneg])
+ : Q_scope.
+
(** A light notation for [Zpos] *)
Lemma Qmake_Qdiv a b : a#b==inject_Z a/inject_Z (Zpos b).
diff --git a/theories/QArith/Qreals.v b/theories/QArith/Qreals.v
index 1baefd6bf7..20b5cb236b 100644
--- a/theories/QArith/Qreals.v
+++ b/theories/QArith/Qreals.v
@@ -13,8 +13,6 @@ Require Export QArith_base.
(** Injection of rational numbers into real numbers. *)
-Definition Q2R (x : Q) : R := (IZR (Qnum x) * / IZR (QDen x))%R.
-
Lemma IZR_nz : forall p : positive, IZR (Zpos p) <> 0%R.
Proof.
intros.
diff --git a/theories/Reals/Rdefinitions.v b/theories/Reals/Rdefinitions.v
index affa129771..40736c61f2 100644
--- a/theories/Reals/Rdefinitions.v
+++ b/theories/Reals/Rdefinitions.v
@@ -22,11 +22,12 @@ Require Import ConstructiveRcomplete.
Require Import ClassicalDedekindReals.
-(* Declare primitive numeral notations for Scope R_scope *)
+(* Declare primitive number notations for Scope R_scope *)
+Declare Scope hex_R_scope.
Declare Scope R_scope.
-Declare ML Module "r_syntax_plugin".
(* Declare Scope R_scope with Key R *)
+Delimit Scope hex_R_scope with xR.
Delimit Scope R_scope with R.
Local Open Scope R_scope.
@@ -224,3 +225,165 @@ Proof.
- (* x = n-1 *) exact n.
- exact (Z.pred n).
Defined.
+
+(** Injection of rational numbers into real numbers. *)
+
+Definition Q2R (x : Q) : R := (IZR (Qnum x) * / IZR (QDen x))%R.
+
+(**********************************************************)
+(** * Number notation for constants *)
+(**********************************************************)
+
+Inductive IR :=
+ | IRZ : IZ -> IR
+ | IRQ : Q -> IR
+ | IRmult : IR -> IR -> IR
+ | IRdiv : IR -> IR -> IR.
+
+Definition of_decimal (d : Decimal.decimal) : IR :=
+ let '(i, f, e) :=
+ match d with
+ | Decimal.Decimal i f => (i, f, Decimal.Pos Decimal.Nil)
+ | Decimal.DecimalExp i f e => (i, f, e)
+ end in
+ let zq := match f with
+ | Decimal.Nil => IRZ (IZ_of_Z (Z.of_int i))
+ | _ =>
+ let num := Z.of_int (Decimal.app_int i f) in
+ let den := Nat.iter (Decimal.nb_digits f) (Pos.mul 10) 1%positive in
+ IRQ (Qmake num den) end in
+ let e := Z.of_int e in
+ match e with
+ | Z0 => zq
+ | Zpos e => IRmult zq (IRZ (IZpow_pos 10 e))
+ | Zneg e => IRdiv zq (IRZ (IZpow_pos 10 e))
+ end.
+
+Definition of_hexadecimal (d : Hexadecimal.hexadecimal) : IR :=
+ let '(i, f, e) :=
+ match d with
+ | Hexadecimal.Hexadecimal i f => (i, f, Decimal.Pos Decimal.Nil)
+ | Hexadecimal.HexadecimalExp i f e => (i, f, e)
+ end in
+ let zq := match f with
+ | Hexadecimal.Nil => IRZ (IZ_of_Z (Z.of_hex_int i))
+ | _ =>
+ let num := Z.of_hex_int (Hexadecimal.app_int i f) in
+ let den := Nat.iter (Hexadecimal.nb_digits f) (Pos.mul 16) 1%positive in
+ IRQ (Qmake num den) end in
+ let e := Z.of_int e in
+ match e with
+ | Z0 => zq
+ | Zpos e => IRmult zq (IRZ (IZpow_pos 2 e))
+ | Zneg e => IRdiv zq (IRZ (IZpow_pos 2 e))
+ end.
+
+Definition of_number (n : Number.number) : IR :=
+ match n with
+ | Number.Decimal d => of_decimal d
+ | Number.Hexadecimal h => of_hexadecimal h
+ end.
+
+Definition IQmake_to_decimal num den :=
+ match den with
+ | 1%positive => None (* this should be encoded as IRZ *)
+ | _ => IQmake_to_decimal num den
+ end.
+
+Definition to_decimal (n : IR) : option Decimal.decimal :=
+ match n with
+ | IRZ z =>
+ match IZ_to_Z z with
+ | Some z => Some (Decimal.Decimal (Z.to_int z) Decimal.Nil)
+ | None => None
+ end
+ | IRQ (Qmake num den) => IQmake_to_decimal num den
+ | IRmult (IRZ z) (IRZ (IZpow_pos 10 e)) =>
+ match IZ_to_Z z with
+ | Some z =>
+ Some (Decimal.DecimalExp (Z.to_int z) Decimal.Nil (Pos.to_int e))
+ | None => None
+ end
+ | IRmult (IRQ (Qmake num den)) (IRZ (IZpow_pos 10 e)) =>
+ match IQmake_to_decimal num den with
+ | Some (Decimal.Decimal i f) =>
+ Some (Decimal.DecimalExp i f (Pos.to_int e))
+ | _ => None
+ end
+ | IRdiv (IRZ z) (IRZ (IZpow_pos 10 e)) =>
+ match IZ_to_Z z with
+ | Some z =>
+ Some (Decimal.DecimalExp (Z.to_int z) Decimal.Nil (Decimal.Neg (Pos.to_uint e)))
+ | None => None
+ end
+ | IRdiv (IRQ (Qmake num den)) (IRZ (IZpow_pos 10 e)) =>
+ match IQmake_to_decimal num den with
+ | Some (Decimal.Decimal i f) =>
+ Some (Decimal.DecimalExp i f (Decimal.Neg (Pos.to_uint e)))
+ | _ => None
+ end
+ | _ => None
+ end.
+
+Definition IQmake_to_hexadecimal num den :=
+ match den with
+ | 1%positive => None (* this should be encoded as IRZ *)
+ | _ => IQmake_to_hexadecimal num den
+ end.
+
+Definition to_hexadecimal (n : IR) : option Hexadecimal.hexadecimal :=
+ match n with
+ | IRZ z =>
+ match IZ_to_Z z with
+ | Some z => Some (Hexadecimal.Hexadecimal (Z.to_hex_int z) Hexadecimal.Nil)
+ | None => None
+ end
+ | IRQ (Qmake num den) => IQmake_to_hexadecimal num den
+ | IRmult (IRZ z) (IRZ (IZpow_pos 2 e)) =>
+ match IZ_to_Z z with
+ | Some z =>
+ Some (Hexadecimal.HexadecimalExp (Z.to_hex_int z) Hexadecimal.Nil (Pos.to_int e))
+ | None => None
+ end
+ | IRmult (IRQ (Qmake num den)) (IRZ (IZpow_pos 2 e)) =>
+ match IQmake_to_hexadecimal num den with
+ | Some (Hexadecimal.Hexadecimal i f) =>
+ Some (Hexadecimal.HexadecimalExp i f (Pos.to_int e))
+ | _ => None
+ end
+ | IRdiv (IRZ z) (IRZ (IZpow_pos 2 e)) =>
+ match IZ_to_Z z with
+ | Some z =>
+ Some (Hexadecimal.HexadecimalExp (Z.to_hex_int z) Hexadecimal.Nil (Decimal.Neg (Pos.to_uint e)))
+ | None => None
+ end
+ | IRdiv (IRQ (Qmake num den)) (IRZ (IZpow_pos 2 e)) =>
+ match IQmake_to_hexadecimal num den with
+ | Some (Hexadecimal.Hexadecimal i f) =>
+ Some (Hexadecimal.HexadecimalExp i f (Decimal.Neg (Pos.to_uint e)))
+ | _ => None
+ end
+ | _ => None
+ end.
+
+Definition to_number q :=
+ match to_decimal q with
+ | None => None
+ | Some q => Some (Number.Decimal q)
+ end.
+
+Definition to_hex_number q :=
+ match to_hexadecimal q with
+ | None => None
+ | Some q => Some (Number.Hexadecimal q)
+ end.
+
+Number Notation R of_number to_hex_number (via IR
+ mapping [IZR => IRZ, Q2R => IRQ, Rmult => IRmult, Rdiv => IRdiv,
+ Z.pow_pos => IZpow_pos, Z0 => IZ0, Zpos => IZpos, Zneg => IZneg])
+ : hex_R_scope.
+
+Number Notation R of_number to_number (via IR
+ mapping [IZR => IRZ, Q2R => IRQ, Rmult => IRmult, Rdiv => IRdiv,
+ Z.pow_pos => IZpow_pos, Z0 => IZ0, Zpos => IZpos, Zneg => IZneg])
+ : R_scope.
diff --git a/theories/Reals/Rregisternames.v b/theories/Reals/Rregisternames.v
index 8b078f2cf3..8117d975fe 100644
--- a/theories/Reals/Rregisternames.v
+++ b/theories/Reals/Rregisternames.v
@@ -8,7 +8,7 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-Require Import Raxioms Rfunctions Qreals.
+Require Import Raxioms Rfunctions.
(*****************************************************************)
(** Register names for use in plugins *)
@@ -31,4 +31,4 @@ Register IZR as reals.R.IZR.
Register Rabs as reals.R.Rabs.
Register powerRZ as reals.R.powerRZ.
Register pow as reals.R.pow.
-Register Qreals.Q2R as reals.R.Q2R.
+Register Q2R as reals.R.Q2R.
diff --git a/theories/Strings/Ascii.v b/theories/Strings/Ascii.v
index c155395ecd..06b02ab211 100644
--- a/theories/Strings/Ascii.v
+++ b/theories/Strings/Ascii.v
@@ -128,28 +128,28 @@ Definition nat_of_ascii (a : ascii) : nat := N.to_nat (N_of_ascii a).
Theorem ascii_N_embedding :
forall a : ascii, ascii_of_N (N_of_ascii a) = a.
Proof.
- destruct a as [[|][|][|][|][|][|][|][|]]; vm_compute; reflexivity.
+ intro a; destruct a as [[|][|][|][|][|][|][|][|]]; vm_compute; reflexivity.
Qed.
Theorem N_ascii_embedding :
forall n:N, (n < 256)%N -> N_of_ascii (ascii_of_N n) = n.
Proof.
-destruct n.
+intro n; destruct n as [|p].
reflexivity.
-do 8 (destruct p; [ | | intros; vm_compute; reflexivity ]);
+do 8 (destruct p as [p|p|]; [ | | intros; vm_compute; reflexivity ]);
intro H; vm_compute in H; destruct p; discriminate.
Qed.
Theorem N_ascii_bounded :
forall a : ascii, (N_of_ascii a < 256)%N.
Proof.
- destruct a as [[|][|][|][|][|][|][|][|]]; vm_compute; reflexivity.
+ intro a; destruct a as [[|][|][|][|][|][|][|][|]]; vm_compute; reflexivity.
Qed.
Theorem ascii_nat_embedding :
forall a : ascii, ascii_of_nat (nat_of_ascii a) = a.
Proof.
- destruct a as [[|][|][|][|][|][|][|][|]]; compute; reflexivity.
+ intro a; destruct a as [[|][|][|][|][|][|][|][|]]; compute; reflexivity.
Qed.
Theorem nat_ascii_embedding :
diff --git a/theories/Strings/String.v b/theories/Strings/String.v
index a468a4fe87..b792acc9f9 100644
--- a/theories/Strings/String.v
+++ b/theories/Strings/String.v
@@ -54,7 +54,8 @@ Infix "=?" := eqb : string_scope.
Lemma eqb_spec s1 s2 : Bool.reflect (s1 = s2) (s1 =? s2)%string.
Proof.
- revert s2. induction s1; destruct s2; try (constructor; easy); simpl.
+ revert s2. induction s1 as [|? s1 IHs1];
+ intro s2; destruct s2; try (constructor; easy); simpl.
case Ascii.eqb_spec; simpl; [intros -> | constructor; now intros [= ]].
case IHs1; [intros ->; now constructor | constructor; now intros [= ]].
Qed.
@@ -117,7 +118,7 @@ intros s1; elim s1; simpl.
intros s2; case s2; simpl; split; auto.
intros H; generalize (H O); intros H1; inversion H1.
intros; discriminate.
-intros a s1' Rec s2; case s2; simpl; split; auto.
+intros a s1' Rec s2; case s2 as [|? s]; simpl; split; auto.
intros H; generalize (H O); intros H1; inversion H1.
intros; discriminate.
intros H; generalize (H O); simpl; intros H1; inversion H1.
@@ -249,7 +250,7 @@ intros b s2'; case (ascii_dec a b); simpl; auto.
intros e; case (Rec s2'); intros H1 H2; split; intros H3; auto.
rewrite e; rewrite H1; auto.
apply H2; injection H3; auto.
-intros n; split; intros; try discriminate.
+intros n; split; intros H; try discriminate.
case n; injection H; auto.
Qed.
diff --git a/theories/Vectors/Fin.v b/theories/Vectors/Fin.v
index 18e286b943..45fcbfb329 100644
--- a/theories/Vectors/Fin.v
+++ b/theories/Vectors/Fin.v
@@ -111,7 +111,7 @@ Qed.
Lemma of_nat_to_nat_inv {m} (p : t m) : of_nat_lt (proj2_sig (to_nat p)) = p.
Proof.
-induction p; simpl.
+induction p as [|? p]; simpl.
- reflexivity.
- destruct (to_nat p); simpl in *. f_equal. subst p. apply of_nat_ext.
Qed.
@@ -119,7 +119,7 @@ Qed.
Lemma to_nat_of_nat {p}{n} (h : p < n) : to_nat (of_nat_lt h) = exist _ p h.
Proof.
revert n h.
- induction p; (destruct n ; intros h; [ destruct (Lt.lt_n_O _ h) | cbn]);
+ induction p as [|p IHp]; (intro n; destruct n as [|n]; intros h; [ destruct (Lt.lt_n_O _ h) | cbn]);
[ | rewrite (IHp _ (Lt.lt_S_n p n h))]; f_equal; apply Peano_dec.le_unique.
Qed.
@@ -153,7 +153,7 @@ Fixpoint L {m} n (p : t m) : t (m + n) :=
Lemma L_sanity {m} n (p : t m) : proj1_sig (to_nat (L n p)) = proj1_sig (to_nat p).
Proof.
-induction p.
+induction p as [|? p IHp].
- reflexivity.
- simpl; destruct (to_nat (L n p)); simpl in *; rewrite IHp. now destruct (to_nat p).
Qed.
@@ -163,7 +163,7 @@ Qed.
Really really inefficient !!! *)
Definition L_R {m} n (p : t m) : t (n + m).
Proof.
-induction n.
+induction n as [|n IHn].
- exact p.
- exact ((fix LS k (p: t k) :=
match p with
@@ -179,7 +179,7 @@ Fixpoint R {m} n (p : t m) : t (n + m) :=
Lemma R_sanity {m} n (p : t m) : proj1_sig (to_nat (R n p)) = n + proj1_sig (to_nat p).
Proof.
-induction n.
+induction n as [|n IHn].
- reflexivity.
- simpl; destruct (to_nat (R n p)); simpl in *; rewrite IHn. now destruct (to_nat p).
Qed.
@@ -193,7 +193,7 @@ end.
Lemma depair_sanity {m n} (o : t m) (p : t n) :
proj1_sig (to_nat (depair o p)) = n * (proj1_sig (to_nat o)) + (proj1_sig (to_nat p)).
Proof.
-induction o ; simpl.
+induction o as [|? o IHo] ; simpl.
- rewrite L_sanity. now rewrite Mult.mult_0_r.
- rewrite R_sanity. rewrite IHo.
@@ -211,7 +211,8 @@ end.
Lemma eqb_nat_eq : forall m n (p : t m) (q : t n), eqb p q = true -> m = n.
Proof.
-intros m n p; revert n; induction p; destruct q; simpl; intros; f_equal.
+intros m n p; revert n; induction p as [|? p IHp];
+ intros ? q; destruct q; simpl; intros; f_equal.
- now apply EqNat.beq_nat_true.
- easy.
- easy.
diff --git a/theories/Vectors/VectorDef.v b/theories/Vectors/VectorDef.v
index 57241e5f42..a154a2b269 100644
--- a/theories/Vectors/VectorDef.v
+++ b/theories/Vectors/VectorDef.v
@@ -167,7 +167,7 @@ Fixpoint take {A} {n} (p:nat) (le:p <= n) (v:t A n) : t A p :=
Lemma trunc : forall {A} {n} (p:nat), n > p -> t A n
-> t A (n - p).
Proof.
- induction p as [| p f]; intros H v.
+ intros A n p; induction p as [| p f]; intros H v.
rewrite <- minus_n_O.
exact v.
diff --git a/theories/Vectors/VectorEq.v b/theories/Vectors/VectorEq.v
index 6bd2c30205..c36917aa90 100644
--- a/theories/Vectors/VectorEq.v
+++ b/theories/Vectors/VectorEq.v
@@ -36,7 +36,7 @@ Section BEQ.
(Hbeq: eqb v1 v2 = true), m = n.
Proof.
intros m n v1; revert n.
- induction v1; destruct v2;
+ induction v1; intros ? v2; destruct v2;
[now constructor | discriminate | discriminate | simpl].
intros Hbeq; apply andb_prop in Hbeq; destruct Hbeq.
f_equal; eauto.
diff --git a/theories/Vectors/VectorSpec.v b/theories/Vectors/VectorSpec.v
index 443931e5bb..10545332bb 100644
--- a/theories/Vectors/VectorSpec.v
+++ b/theories/Vectors/VectorSpec.v
@@ -26,7 +26,7 @@ Definition cons_inj {A} {a1 a2} {n} {v1 v2 : t A n}
Lemma eta {A} {n} (v : t A (S n)) : v = hd v :: tl v.
Proof.
-intros; apply caseS with (v:=v); intros; reflexivity.
+intros; apply (fun P IS => caseS P IS (n := n) v); intros; reflexivity.
Defined.
(** Lemmas are done for functions that use [Fin.t] but thanks to [Peano_dec.le_unique], all
@@ -38,9 +38,9 @@ Lemma eq_nth_iff A n (v1 v2: t A n):
(forall p1 p2, p1 = p2 -> v1 [@ p1 ] = v2 [@ p2 ]) <-> v1 = v2.
Proof.
split.
-- revert n v1 v2; refine (@rect2 _ _ _ _ _); simpl; intros.
+- revert n v1 v2; refine (@rect2 _ _ _ _ _); simpl.
+ reflexivity.
- + f_equal. apply (H0 Fin.F1 Fin.F1 eq_refl).
+ + intros n ? ? H ? ? H0. f_equal. apply (H0 Fin.F1 Fin.F1 eq_refl).
apply H. intros p1 p2 H1;
apply (H0 (Fin.FS p1) (Fin.FS p2) (f_equal (@Fin.FS n) H1)).
- intros; now f_equal.
@@ -48,12 +48,12 @@ Qed.
Lemma nth_order_hd A: forall n (v : t A (S n)) (H : 0 < S n),
nth_order v H = hd v.
-Proof. intros; now rewrite (eta v). Qed.
+Proof. intros n v H; now rewrite (eta v). Qed.
Lemma nth_order_tl A: forall n k (v : t A (S n)) (H : k < n) (HS : S k < S n),
nth_order (tl v) H = nth_order v HS.
Proof.
-induction n; intros.
+intros n; induction n; intros k v H HS.
- inversion H.
- rewrite (eta v).
unfold nth_order; simpl.
@@ -69,7 +69,7 @@ Qed.
Lemma nth_order_ext A: forall n k (v : t A n) (H1 H2 : k < n),
nth_order v H1 = nth_order v H2.
Proof.
-intros; unfold nth_order.
+intros n k v H1 H2; unfold nth_order.
now rewrite (Fin.of_nat_ext H1 H2).
Qed.
@@ -78,7 +78,7 @@ Qed.
Lemma shiftin_nth A a n (v: t A n) k1 k2 (eq: k1 = k2):
nth (shiftin a v) (Fin.L_R 1 k1) = nth v k2.
Proof.
-subst k2; induction k1.
+subst k2; induction k1 as [n|n k1].
- generalize dependent n. apply caseS ; intros. now simpl.
- generalize dependent n. refine (@caseS _ _ _) ; intros. now simpl.
Qed.
@@ -92,14 +92,14 @@ Lemma shiftrepeat_nth A: forall n k (v: t A (S n)),
nth (shiftrepeat v) (Fin.L_R 1 k) = nth v k.
Proof.
refine (@Fin.rectS _ _ _); lazy beta; [ intros n v | intros n p H v ].
-- revert n v; refine (@caseS _ _ _); simpl; intros. now destruct t.
+- revert n v; refine (@caseS _ _ _); simpl; intros ? ? t. now destruct t.
- revert p H.
refine (match v as v' in t _ m return match m as m' return t A m' -> Prop with
|S (S n) => fun v => forall p : Fin.t (S n),
(forall v0 : t A (S n), (shiftrepeat v0) [@ Fin.L_R 1 p ] = v0 [@p]) ->
(shiftrepeat v) [@Fin.L_R 1 (Fin.FS p)] = v [@Fin.FS p]
|_ => fun _ => True end v' with
- |[] => I |h :: t => _ end). destruct n0. exact I. now simpl.
+ |[] => I | cons _ h n t => _ end). destruct n. exact I. now simpl.
Qed.
Lemma shiftrepeat_last A: forall n (v: t A (S n)), last (shiftrepeat v) = last v.
@@ -112,7 +112,7 @@ Qed.
Lemma nth_order_replace_eq A: forall n k (v : t A n) a (H1 : k < n) (H2 : k < n),
nth_order (replace v (Fin.of_nat_lt H2) a) H1 = a.
Proof.
-intros n k; revert n; induction k; intros;
+intros n k; revert n; induction k as [|k IHk]; intros n v a H1 H2;
(destruct n; [ inversion H1 | subst ]).
- now rewrite nth_order_hd, (eta v).
- rewrite <- (nth_order_tl _ _ _ _ (proj2 (Nat.succ_lt_mono _ _) H1)), (eta v).
@@ -123,7 +123,7 @@ Lemma nth_order_replace_neq A: forall n k1 k2, k1 <> k2 ->
forall (v : t A n) a (H1 : k1 < n) (H2 : k2 < n),
nth_order (replace v (Fin.of_nat_lt H2) a) H1 = nth_order v H1.
Proof.
-intros n k1; revert n; induction k1; intros;
+intros n k1; revert n; induction k1 as [|k1 IHk1]; intros n k2 H v a H1 H2;
(destruct n ; [ inversion H1 | subst ]).
- rewrite 2 nth_order_hd.
destruct k2; intuition.
@@ -137,15 +137,15 @@ Qed.
Lemma replace_id A: forall n p (v : t A n),
replace v p (nth v p) = v.
Proof.
-induction p; intros; rewrite 2 (eta v); simpl; auto.
+intros n p; induction p as [|? p IHp]; intros v; rewrite 2 (eta v); simpl; auto.
now rewrite IHp.
Qed.
Lemma replace_replace_eq A: forall n p (v : t A n) a b,
replace (replace v p a) p b = replace v p b.
Proof.
-intros.
-induction p; rewrite 2 (eta v); simpl; auto.
+intros n p v a b.
+induction p as [|? p IHp]; rewrite 2 (eta v); simpl; auto.
now rewrite IHp.
Qed.
@@ -161,7 +161,7 @@ apply (Fin.rect2 (fun n p1 p2 => forall v a b,
- intros n p1 v; revert n v p1.
refine (@rectS _ _ _ _); auto.
- intros n p1 p2 IH v; revert n v p1 p2 IH.
- refine (@rectS _ _ _ _); simpl; do 6 intro; [ | do 3 intro ]; intro Hneq;
+ refine (@rectS _ _ _ _); simpl; intro n; [| do 3 intro]; intros ? ? IH p1 p2; intro Hneq;
f_equal; apply IH; intros Heq; apply Hneq; now subst.
Qed.
@@ -177,19 +177,19 @@ Qed.
Lemma map_id A: forall n (v : t A n),
map (fun x => x) v = v.
Proof.
-induction v; simpl; [ | rewrite IHv ]; auto.
+intros n v; induction v as [|? ? v IHv]; simpl; [ | rewrite IHv ]; auto.
Qed.
Lemma map_map A B C: forall (f:A->B) (g:B->C) n (v : t A n),
map g (map f v) = map (fun x => g (f x)) v.
Proof.
-induction v; simpl; [ | rewrite IHv ]; auto.
+intros f g n v; induction v as [|? ? v IHv]; simpl; [ | rewrite IHv ]; auto.
Qed.
Lemma map_ext_in A B: forall (f g:A->B) n (v : t A n),
(forall a, In a v -> f a = g a) -> map f v = map g v.
Proof.
-induction v; simpl; auto.
+intros f g n v H; induction v as [|? ? v IHv]; simpl; auto.
intros; rewrite H by constructor; rewrite IHv; intuition.
apply H; now constructor.
Qed.
@@ -203,7 +203,7 @@ Qed.
Lemma nth_map {A B} (f: A -> B) {n} v (p1 p2: Fin.t n) (eq: p1 = p2):
(map f v) [@ p1] = f (v [@ p2]).
Proof.
-subst p2; induction p1.
+subst p2; induction p1 as [n|n p1 IHp1].
- revert n v; refine (@caseS _ _ _); now simpl.
- revert n v p1 IHp1; refine (@caseS _ _ _); now simpl.
Qed.
@@ -225,10 +225,10 @@ Lemma fold_left_right_assoc_eq {A B} {f: A -> B -> A}
{n} (v: t B n): forall a, fold_left f a v = fold_right (fun x y => f y x) v a.
Proof.
assert (forall n h (v: t B n) a, fold_left f (f a h) v = f (fold_left f a v) h).
-- induction v0.
+- intros n0 h v0; induction v0 as [|? ? v0 IHv0].
+ now simpl.
+ intros; simpl. rewrite<- IHv0, assoc. now f_equal.
-- induction v.
+- induction v as [|? ? v IHv].
+ reflexivity.
+ simpl. intros; now rewrite<- (IHv).
Qed.
@@ -245,31 +245,31 @@ Qed.
(** ** Properties of [take] *)
Lemma take_O : forall {A} {n} le (v:t A n), take 0 le v = [].
-Proof.
+Proof.
reflexivity.
-Qed.
+Qed.
Lemma take_idem : forall {A} p n (v:t A n) le le',
take p le' (take p le v) = take p le v.
-Proof.
- induction p; intros n v le le'.
- - auto.
- - destruct v. inversion le. simpl. apply f_equal. apply IHp.
+Proof.
+ intros A p; induction p as [|p IHp]; intros n v le le'.
+ - auto.
+ - destruct v. inversion le. simpl. apply f_equal. apply IHp.
Qed.
Lemma take_app : forall {A} {n} (v:t A n) {m} (w:t A m) le, take n le (append v w) = v.
-Proof.
- induction v; intros m w le.
- - reflexivity.
- - simpl. apply f_equal. apply IHv.
+Proof.
+ intros a n v; induction v as [|? ? v IHv]; intros m w le.
+ - reflexivity.
+ - simpl. apply f_equal. apply IHv.
Qed.
(* Proof is irrelevant for [take] *)
Lemma take_prf_irr : forall {A} p {n} (v:t A n) le le', take p le v = take p le' v.
-Proof.
- induction p; intros n v le le'.
- - reflexivity.
- - destruct v. inversion le. simpl. apply f_equal. apply IHp.
+Proof.
+ intros A p; induction p as [|p IHp]; intros n v le le'.
+ - reflexivity.
+ - destruct v. inversion le. simpl. apply f_equal. apply IHp.
Qed.
(** ** Properties of [uncons] and [splitat] *)
@@ -289,7 +289,7 @@ Lemma splitat_append {A} : forall {n m : nat} (v : t A n) (w : t A m),
Proof with simpl; auto.
intros n m v.
generalize dependent m.
- induction v; intros...
+ induction v as [|? ? v IHv]; intros...
rewrite IHv...
Qed.
@@ -299,10 +299,10 @@ Lemma append_splitat {A} : forall {n m : nat} (v : t A n) (w : t A m) (vw : t A
Proof with auto.
intros n m v.
generalize dependent m.
- induction v; intros; inversion H...
+ induction v as [|a n v IHv]; intros m w vw H; inversion H as [H1]...
destruct (splitat n (tl vw)) as [v' w'] eqn:Heq.
apply pair_equal_spec in H1.
- destruct H1; subst.
+ destruct H1 as [H0]; subst.
rewrite <- append_comm_cons.
rewrite (eta vw).
apply cons_inj in H0.
@@ -316,7 +316,7 @@ Qed.
Lemma Forall_impl A: forall (P Q : A -> Prop), (forall a, P a -> Q a) ->
forall n (v : t A n), Forall P v -> Forall Q v.
Proof.
-induction v; intros HP; constructor; inversion HP as [| ? ? ? ? ? Heq1 [Heq2 He]];
+intros P Q H n v; induction v; intros HP; constructor; inversion HP as [| ? ? ? ? ? Heq1 [Heq2 He]];
apply (inj_pair2_eq_dec _ Nat.eq_dec) in He; subst; intuition.
Qed.
@@ -328,7 +328,7 @@ intros P n v; split.
revert HP; induction Hin; intros HP;
inversion HP as [| ? ? ? ? ? Heq1 [Heq2 He]]; subst; auto.
apply (inj_pair2_eq_dec _ Nat.eq_dec) in He; subst; auto.
-- induction v; intros Hin; constructor.
+- induction v as [|? ? v IHv]; intros Hin; constructor.
+ apply Hin; constructor.
+ apply IHv; intros a Ha.
apply Hin; now constructor.
@@ -337,7 +337,7 @@ Qed.
Lemma Forall_nth_order A: forall P n (v : t A n),
Forall P v <-> forall i (Hi : i < n), P (nth_order v Hi).
Proof.
-split; induction n.
+intros P n v; split; induction n as [|n IHn].
- intros HF i Hi; inversion Hi.
- intros HF i Hi.
rewrite (eta v).
@@ -354,7 +354,7 @@ split; induction n.
rewrite (eta v); constructor.
+ specialize HP with 0 (Nat.lt_0_succ n).
now rewrite nth_order_hd in HP.
- + apply IHn; intros.
+ + apply IHn; intros i Hi.
specialize HP with (S i) (proj1 (Nat.succ_lt_mono _ _) Hi).
now rewrite <- (nth_order_tl _ _ _ _ Hi) in HP.
Qed.
@@ -363,7 +363,7 @@ Lemma Forall2_nth_order A: forall P n (v1 v2 : t A n),
Forall2 P v1 v2
<-> forall i (Hi1 : i < n) (Hi2 : i < n), P (nth_order v1 Hi1) (nth_order v2 Hi2).
Proof.
-split; induction n.
+intros P n v1 v2; split; induction n as [|n IHn].
- intros HF i Hi1 Hi2; inversion Hi1.
- intros HF i Hi1 Hi2.
rewrite (eta v1), (eta v2).
@@ -382,7 +382,7 @@ split; induction n.
rewrite (eta v1), (eta v2); constructor.
+ specialize HP with 0 (Nat.lt_0_succ _) (Nat.lt_0_succ _).
now rewrite nth_order_hd in HP.
- + apply IHn; intros.
+ + apply IHn; intros i Hi1 Hi2.
specialize HP with (S i) (proj1 (Nat.succ_lt_mono _ _) Hi1)
(proj1 (Nat.succ_lt_mono _ _) Hi2).
now rewrite <- (nth_order_tl _ _ _ _ Hi1), <- (nth_order_tl _ _ _ _ Hi2) in HP.
diff --git a/theories/ZArith/BinInt.v b/theories/ZArith/BinInt.v
index 9a30e011af..52998c8b95 100644
--- a/theories/ZArith/BinInt.v
+++ b/theories/ZArith/BinInt.v
@@ -126,7 +126,7 @@ Lemma pos_sub_spec p q :
| Gt => pos (p - q)
end.
Proof.
- revert q. induction p; destruct q; simpl; trivial;
+ revert q. induction p as [p IHp|p IHp|]; intros q; destruct q; simpl; trivial;
rewrite ?Pos.compare_xI_xI, ?Pos.compare_xO_xI,
?Pos.compare_xI_xO, ?Pos.compare_xO_xO, IHp; simpl;
case Pos.compare_spec; intros; simpl; trivial;
@@ -168,7 +168,7 @@ Qed.
Lemma pos_sub_opp p q : - pos_sub p q = pos_sub q p.
Proof.
- revert q; induction p; destruct q; simpl; trivial;
+ revert q; induction p as [p IHp|p IHp|]; intros q; destruct q; simpl; trivial;
rewrite <- IHp; now destruct pos_sub.
Qed.
@@ -468,13 +468,13 @@ Lemma peano_ind (P : Z -> Prop) :
(forall x, P x -> P (pred x)) ->
forall z, P z.
Proof.
- intros H0 Hs Hp z; destruct z.
+ intros H0 Hs Hp z; destruct z as [|p|p].
assumption.
- induction p using Pos.peano_ind.
+ induction p as [|p IHp] using Pos.peano_ind.
now apply (Hs 0).
rewrite <- Pos.add_1_r.
now apply (Hs (pos p)).
- induction p using Pos.peano_ind.
+ induction p as [|p IHp] using Pos.peano_ind.
now apply (Hp 0).
rewrite <- Pos.add_1_r.
now apply (Hp (neg p)).
@@ -486,7 +486,7 @@ Lemma bi_induction (P : Z -> Prop) :
(forall x, P x <-> P (succ x)) ->
forall z, P z.
Proof.
- intros _ H0 Hs. induction z using peano_ind.
+ intros _ H0 Hs z. induction z using peano_ind.
assumption.
now apply -> Hs.
apply Hs. now rewrite succ_pred.
@@ -569,7 +569,7 @@ Qed.
Lemma sqrtrem_spec n : 0<=n ->
let (s,r) := sqrtrem n in n = s*s + r /\ 0 <= r <= 2*s.
Proof.
- destruct n. now repeat split.
+ destruct n as [|p|p]. now repeat split.
generalize (Pos.sqrtrem_spec p). simpl.
destruct 1; simpl; subst; now repeat split.
now destruct 1.
@@ -578,7 +578,7 @@ Qed.
Lemma sqrt_spec n : 0<=n ->
let s := sqrt n in s*s <= n < (succ s)*(succ s).
Proof.
- destruct n. now repeat split. unfold sqrt.
+ destruct n as [|p|p]. now repeat split. unfold sqrt.
intros _. simpl succ. rewrite Pos.add_1_r. apply (Pos.sqrt_spec p).
now destruct 1.
Qed.
@@ -590,7 +590,7 @@ Qed.
Lemma sqrtrem_sqrt n : fst (sqrtrem n) = sqrt n.
Proof.
- destruct n; try reflexivity.
+ destruct n as [|p|p]; try reflexivity.
unfold sqrtrem, sqrt, Pos.sqrt.
destruct (Pos.sqrtrem p) as (s,r). now destruct r.
Qed.
@@ -655,7 +655,7 @@ Lemma pos_div_eucl_eq a b : 0 < b ->
let (q, r) := pos_div_eucl a b in pos a = q * b + r.
Proof.
intros Hb.
- induction a; unfold pos_div_eucl; fold pos_div_eucl.
+ induction a as [a IHa|a IHa|]; unfold pos_div_eucl; fold pos_div_eucl.
- (* ~1 *)
destruct pos_div_eucl as (q,r).
change (pos a~1) with (2*(pos a)+1).
@@ -720,7 +720,7 @@ Proof.
now rewrite Pos.add_diag.
intros Hb.
destruct b as [|b|b]; discriminate Hb || clear Hb.
- induction a; unfold pos_div_eucl; fold pos_div_eucl.
+ induction a as [a IHa|a IHa|]; unfold pos_div_eucl; fold pos_div_eucl.
(* ~1 *)
destruct pos_div_eucl as (q,r).
simpl in IHa; destruct IHa as (Hr,Hr').
@@ -996,7 +996,7 @@ Proof.
intros Hn Hm. unfold shiftr.
destruct n as [ |n|n]; (now destruct Hn) || clear Hn; simpl.
now rewrite add_0_r.
- assert (forall p, to_N (m + pos p) = (to_N m + N.pos p)%N).
+ assert (forall p, to_N (m + pos p) = (to_N m + N.pos p)%N) as H.
destruct m; trivial; now destruct Hm.
assert (forall p, 0 <= m + pos p).
destruct m; easy || now destruct Hm.
@@ -1054,7 +1054,7 @@ Proof.
subst. now rewrite N.sub_diag.
simpl. destruct (Pos.sub_mask_pos' m n H') as (p & -> & <-).
f_equal. now rewrite Pos.add_comm, Pos.add_sub.
- destruct a; unfold shiftl.
+ destruct a as [|p|p]; unfold shiftl.
(* ... a = 0 *)
replace (Pos.iter (mul 2) 0 n) with 0
by (apply Pos.iter_invariant; intros; subst; trivial).
diff --git a/theories/ZArith/BinIntDef.v b/theories/ZArith/BinIntDef.v
index 69ed101f24..58bc75b62c 100644
--- a/theories/ZArith/BinIntDef.v
+++ b/theories/ZArith/BinIntDef.v
@@ -311,10 +311,10 @@ Definition of_uint (d:Decimal.uint) := of_N (Pos.of_uint d).
Definition of_hex_uint (d:Hexadecimal.uint) := of_N (Pos.of_hex_uint d).
-Definition of_num_uint (d:Numeral.uint) :=
+Definition of_num_uint (d:Number.uint) :=
match d with
- | Numeral.UIntDec d => of_uint d
- | Numeral.UIntHex d => of_hex_uint d
+ | Number.UIntDecimal d => of_uint d
+ | Number.UIntHexadecimal d => of_hex_uint d
end.
Definition of_int (d:Decimal.int) :=
@@ -329,10 +329,10 @@ Definition of_hex_int (d:Hexadecimal.int) :=
| Hexadecimal.Neg d => opp (of_hex_uint d)
end.
-Definition of_num_int (d:Numeral.int) :=
+Definition of_num_int (d:Number.int) :=
match d with
- | Numeral.IntDec d => of_int d
- | Numeral.IntHex d => of_hex_int d
+ | Number.IntDecimal d => of_int d
+ | Number.IntHexadecimal d => of_hex_int d
end.
Definition to_int n :=
@@ -349,7 +349,7 @@ Definition to_hex_int n :=
| neg p => Hexadecimal.Neg (Pos.to_hex_uint p)
end.
-Definition to_num_int n := Numeral.IntDec (to_int n).
+Definition to_num_int n := Number.IntDecimal (to_int n).
(** ** Iteration of a function
diff --git a/theories/ZArith/Wf_Z.v b/theories/ZArith/Wf_Z.v
index 62fccf3ce2..9fa05dd2f7 100644
--- a/theories/ZArith/Wf_Z.v
+++ b/theories/ZArith/Wf_Z.v
@@ -67,7 +67,7 @@ Lemma natlike_ind :
forall x:Z, 0 <= x -> P x.
Proof.
intros P Ho Hrec x Hx; apply Z_of_nat_prop; trivial.
- induction n. exact Ho.
+ intros n; induction n. exact Ho.
rewrite Nat2Z.inj_succ. apply Hrec; trivial using Nat2Z.is_nonneg.
Qed.
@@ -78,7 +78,7 @@ Lemma natlike_rec :
forall x:Z, 0 <= x -> P x.
Proof.
intros P Ho Hrec x Hx; apply Z_of_nat_set; trivial.
- induction n. exact Ho.
+ intros n; induction n. exact Ho.
rewrite Nat2Z.inj_succ. apply Hrec; trivial using Nat2Z.is_nonneg.
Qed.
@@ -101,9 +101,9 @@ Section Efficient_Rec.
(forall z:Z, 0 <= z -> P z -> P (Z.succ z)) ->
forall z:Z, 0 <= z -> P z.
Proof.
- intros P Ho Hrec.
+ intros P Ho Hrec z.
induction z as [z IH] using (well_founded_induction_type R_wf).
- destruct z; intros Hz.
+ destruct z as [|p|p]; intros Hz.
- apply Ho.
- set (y:=Z.pred (Zpos p)).
assert (LE : 0 <= y) by (unfold y; now apply Z.lt_le_pred).
@@ -121,9 +121,9 @@ Section Efficient_Rec.
(forall z:Z, 0 < z -> P (Z.pred z) -> P z) ->
forall z:Z, 0 <= z -> P z.
Proof.
- intros P Ho Hrec.
+ intros P Ho Hrec z.
induction z as [z IH] using (well_founded_induction_type R_wf).
- destruct z; intros Hz.
+ destruct z as [|p|p]; intros Hz.
- apply Ho.
- assert (EQ : 0 <= Z.pred (Zpos p)) by now apply Z.lt_le_pred.
apply Hrec. easy. apply IH; trivial. split; trivial.
@@ -138,7 +138,7 @@ Section Efficient_Rec.
(forall x:Z, (forall y:Z, 0 <= y < x -> P y) -> 0 <= x -> P x) ->
forall x:Z, 0 <= x -> P x.
Proof.
- intros P Hrec.
+ intros P Hrec x.
induction x as [x IH] using (well_founded_induction_type R_wf).
destruct x; intros Hx.
- apply Hrec; trivial. intros y (Hy,Hy').
@@ -196,7 +196,7 @@ Section Efficient_Rec.
(forall x:Z, (forall y:Z, z <= y < x -> P y) -> z <= x -> P x) ->
forall x:Z, z <= x -> P x.
Proof.
- intros; now apply Zlt_lower_bound_rec with z.
+ intros P z ? x ?; now apply Zlt_lower_bound_rec with z.
Qed.
End Efficient_Rec.
diff --git a/theories/ZArith/ZArith_dec.v b/theories/ZArith/ZArith_dec.v
index 834f16cd9e..dc40f9ea51 100644
--- a/theories/ZArith/ZArith_dec.v
+++ b/theories/ZArith/ZArith_dec.v
@@ -19,7 +19,7 @@ Local Open Scope Z_scope.
(* Trivial, to deprecate? *)
Lemma Dcompare_inf : forall r:comparison, {r = Eq} + {r = Lt} + {r = Gt}.
Proof.
- induction r; auto.
+ intros r; induction r; auto.
Defined.
(* end hide *)
@@ -92,7 +92,7 @@ Section decidability.
Definition Z_le_lt_eq_dec : x <= y -> {x < y} + {x = y}.
Proof.
intro H.
- apply Zcompare_rec with (n := x) (m := y).
+ apply (Zcompare_rec _ x y).
intro. right. elim (Z.compare_eq_iff x y); auto with arith.
intro. left. elim (Z.compare_eq_iff x y); auto with arith.
intro H1. absurd (x > y); auto with arith.
@@ -111,7 +111,7 @@ Proof.
assumption.
intro.
right.
- apply Z.le_lt_trans with (m := x).
+ apply (Z.le_lt_trans _ x).
apply Z.ge_le.
assumption.
assumption.
@@ -123,14 +123,14 @@ Proof.
case (Zlt_cotrans 0 (x + y) H x).
- now left.
- right.
- apply Z.add_lt_mono_l with (p := x).
+ apply (Z.add_lt_mono_l _ _ x).
now rewrite Z.add_0_r.
Defined.
Lemma Zlt_cotrans_neg : forall n m:Z, n + m < 0 -> {n < 0} + {m < 0}.
Proof.
intros x y H; case (Zlt_cotrans (x + y) 0 H x); intro Hxy;
- [ right; apply Z.add_lt_mono_l with (p := x); rewrite Z.add_0_r | left ];
+ [ right; apply (Z.add_lt_mono_l _ _ x); rewrite Z.add_0_r | left ];
assumption.
Defined.
@@ -143,7 +143,7 @@ Proof.
assumption.
intro H0.
generalize (Z.ge_le _ _ H0).
- intro.
+ intro H1.
case (Z_le_lt_eq_dec _ _ H1).
intro.
right.
diff --git a/theories/ZArith/Zabs.v b/theories/ZArith/Zabs.v
index 21086d9b61..f869e15023 100644
--- a/theories/ZArith/Zabs.v
+++ b/theories/ZArith/Zabs.v
@@ -49,12 +49,12 @@ Qed.
Theorem Zabs_intro : forall P (n:Z), P (- n) -> P n -> P (Z.abs n).
Proof.
- now destruct n.
+ intros P n; now destruct n.
Qed.
Definition Zabs_dec : forall x:Z, {x = Z.abs x} + {x = - Z.abs x}.
Proof.
- destruct x; auto.
+ intros x; destruct x; auto.
Defined.
Lemma Zabs_spec x :
diff --git a/theories/ZArith/Zcomplements.v b/theories/ZArith/Zcomplements.v
index c9e1b340a6..c848623d06 100644
--- a/theories/ZArith/Zcomplements.v
+++ b/theories/ZArith/Zcomplements.v
@@ -13,7 +13,6 @@ Require Import ZArith_base.
Require Import Wf_nat.
Local Open Scope Z_scope.
-
(**********************************************************************)
(** About parity *)
@@ -39,7 +38,7 @@ Proof. reflexivity. Qed.
Lemma floor_ok : forall p:positive, floor p <= Zpos p < 2 * floor p.
Proof.
- unfold floor. induction p as [p [IH1p IH2p]|p [IH1p IH2]|]; simpl.
+ unfold floor. intros p; induction p as [p [IH1p IH2p]|p [IH1p IH2]|]; simpl.
- rewrite !Pos2Z.inj_xI, (Pos2Z.inj_xO (xO _)), Pos2Z.inj_xO.
split.
+ apply Z.le_trans with (2 * Z.pos p); auto with zarith.
@@ -69,10 +68,10 @@ Proof.
apply (Z_lt_rec Q); auto with zarith.
subst Q; intros x H.
split; apply HP.
- - rewrite Z.abs_eq; auto; intros.
+ - rewrite Z.abs_eq; auto; intros m ?.
destruct (H (Z.abs m)); auto with zarith.
destruct (Zabs_dec m) as [-> | ->]; trivial.
- - rewrite Z.abs_neq, Z.opp_involutive; intros.
+ - rewrite Z.abs_neq, Z.opp_involutive; [intros m ?|].
+ destruct (H (Z.abs m)); auto with zarith.
destruct (Zabs_dec m) as [-> | ->]; trivial.
+ apply Z.opp_le_mono; rewrite Z.opp_involutive; auto.
@@ -85,15 +84,15 @@ Theorem Z_lt_abs_induction :
Proof.
intros P HP p.
set (Q := fun z => 0 <= z -> P z /\ P (- z)) in *.
- enough (Q (Z.abs p)) by
+ enough (Q (Z.abs p)) as H by
(destruct (Zabs_dec p) as [-> | ->]; elim H; auto with zarith).
apply (Z_lt_induction Q); auto with zarith.
- subst Q; intros.
+ subst Q; intros ? H.
split; apply HP.
- - rewrite Z.abs_eq; auto; intros.
+ - rewrite Z.abs_eq; auto; intros m ?.
elim (H (Z.abs m)); intros; auto with zarith.
elim (Zabs_dec m); intro eq; rewrite eq; trivial.
- - rewrite Z.abs_neq, Z.opp_involutive; intros.
+ - rewrite Z.abs_neq, Z.opp_involutive; [intros m ?|].
+ destruct (H (Z.abs m)); auto with zarith.
destruct (Zabs_dec m) as [-> | ->]; trivial.
+ apply Z.opp_le_mono; rewrite Z.opp_involutive; auto.
@@ -136,7 +135,7 @@ Section Zlength_properties.
Lemma Zlength_correct l : Zlength l = Z.of_nat (length l).
Proof.
assert (H : forall l acc, Zlength_aux acc A l = acc + Z.of_nat (length l)).
- clear l. induction l.
+ clear l. intros l; induction l as [|? ? IHl].
auto with zarith.
intros. simpl length; simpl Zlength_aux.
rewrite IHl, Nat2Z.inj_succ, Z.add_succ_comm; auto.
diff --git a/theories/ZArith/Zdiv.v b/theories/ZArith/Zdiv.v
index b6fbe64499..2039dc0bee 100644
--- a/theories/ZArith/Zdiv.v
+++ b/theories/ZArith/Zdiv.v
@@ -174,22 +174,22 @@ Proof. intros; eapply Zmod_unique_full; eauto. Qed.
Lemma Zmod_0_l: forall a, 0 mod a = 0.
Proof.
- destruct a; simpl; auto.
+ intros a; destruct a; simpl; auto.
Qed.
Lemma Zmod_0_r: forall a, a mod 0 = 0.
Proof.
- destruct a; simpl; auto.
+ intros a; destruct a; simpl; auto.
Qed.
Lemma Zdiv_0_l: forall a, 0/a = 0.
Proof.
- destruct a; simpl; auto.
+ intros a; destruct a; simpl; auto.
Qed.
Lemma Zdiv_0_r: forall a, a/0 = 0.
Proof.
- destruct a; simpl; auto.
+ intros a; destruct a; simpl; auto.
Qed.
Ltac zero_or_not a :=
@@ -198,10 +198,10 @@ Ltac zero_or_not a :=
auto with zarith|].
Lemma Zmod_1_r: forall a, a mod 1 = 0.
-Proof. intros. zero_or_not a. apply Z.mod_1_r. Qed.
+Proof. intros a. zero_or_not a. apply Z.mod_1_r. Qed.
Lemma Zdiv_1_r: forall a, a/1 = a.
-Proof. intros. zero_or_not a. apply Z.div_1_r. Qed.
+Proof. intros a. zero_or_not a. apply Z.div_1_r. Qed.
Hint Resolve Zmod_0_l Zmod_0_r Zdiv_0_l Zdiv_0_r Zdiv_1_r Zmod_1_r
: zarith.
@@ -216,10 +216,10 @@ Lemma Z_div_same_full : forall a:Z, a<>0 -> a/a = 1.
Proof Z.div_same.
Lemma Z_mod_same_full : forall a, a mod a = 0.
-Proof. intros. zero_or_not a. apply Z.mod_same; auto. Qed.
+Proof. intros a. zero_or_not a. apply Z.mod_same; auto. Qed.
Lemma Z_mod_mult : forall a b, (a*b) mod b = 0.
-Proof. intros. zero_or_not b. apply Z.mod_mul. auto. Qed.
+Proof. intros a b. zero_or_not b. apply Z.mod_mul. auto. Qed.
Lemma Z_div_mult_full : forall a b:Z, b <> 0 -> (a*b)/b = a.
Proof Z.div_mul.
@@ -313,7 +313,7 @@ Proof. intros; apply Z.div_le_compat_l; intuition auto using Z.lt_le_incl. Qed.
Theorem Zdiv_sgn: forall a b,
0 <= Z.sgn (a/b) * Z.sgn a * Z.sgn b.
Proof.
- destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith;
+ intros a b; destruct a as [ |a|a]; destruct b as [ |b|b]; simpl; auto with zarith;
generalize (Z.div_pos (Zpos a) (Zpos b)); unfold Z.div, Z.div_eucl;
destruct Z.pos_div_eucl as (q,r); destruct r;
rewrite ?Z.mul_1_r, <-?Z.opp_eq_mul_m1, ?Z.sgn_opp, ?Z.opp_involutive;
@@ -325,7 +325,7 @@ Qed.
(** * Relations between usual operations and Z.modulo and Z.div *)
Lemma Z_mod_plus_full : forall a b c:Z, (a + b * c) mod c = a mod c.
-Proof. intros. zero_or_not c. apply Z.mod_add; auto. Qed.
+Proof. intros a b c. zero_or_not c. apply Z.mod_add; auto. Qed.
Lemma Z_div_plus_full : forall a b c:Z, c <> 0 -> (a + b * c) / c = a / c + b.
Proof Z.div_add.
@@ -338,34 +338,34 @@ Proof Z.div_add_l.
some of the relations about [Z.opp] and divisions are rather complex. *)
Lemma Zdiv_opp_opp : forall a b:Z, (-a)/(-b) = a/b.
-Proof. intros. zero_or_not b. apply Z.div_opp_opp; auto. Qed.
+Proof. intros a b. zero_or_not b. apply Z.div_opp_opp; auto. Qed.
Lemma Zmod_opp_opp : forall a b:Z, (-a) mod (-b) = - (a mod b).
-Proof. intros. zero_or_not b. apply Z.mod_opp_opp; auto. Qed.
+Proof. intros a b. zero_or_not b. apply Z.mod_opp_opp; auto. Qed.
Lemma Z_mod_zero_opp_full : forall a b:Z, a mod b = 0 -> (-a) mod b = 0.
-Proof. intros. zero_or_not b. apply Z.mod_opp_l_z; auto. Qed.
+Proof. intros a b. zero_or_not b. apply Z.mod_opp_l_z; auto. Qed.
Lemma Z_mod_nz_opp_full : forall a b:Z, a mod b <> 0 ->
(-a) mod b = b - (a mod b).
-Proof. intros. zero_or_not b. apply Z.mod_opp_l_nz; auto. Qed.
+Proof. intros a b. zero_or_not b. apply Z.mod_opp_l_nz; auto. Qed.
Lemma Z_mod_zero_opp_r : forall a b:Z, a mod b = 0 -> a mod (-b) = 0.
-Proof. intros. zero_or_not b. apply Z.mod_opp_r_z; auto. Qed.
+Proof. intros a b. zero_or_not b. apply Z.mod_opp_r_z; auto. Qed.
Lemma Z_mod_nz_opp_r : forall a b:Z, a mod b <> 0 ->
a mod (-b) = (a mod b) - b.
-Proof. intros. zero_or_not b. apply Z.mod_opp_r_nz; auto. Qed.
+Proof. intros a b ?. zero_or_not b. apply Z.mod_opp_r_nz; auto. Qed.
Lemma Z_div_zero_opp_full : forall a b:Z, a mod b = 0 -> (-a)/b = -(a/b).
-Proof. intros. zero_or_not b. apply Z.div_opp_l_z; auto. Qed.
+Proof. intros a b ?. zero_or_not b. apply Z.div_opp_l_z; auto. Qed.
Lemma Z_div_nz_opp_full : forall a b:Z, a mod b <> 0 ->
(-a)/b = -(a/b)-1.
Proof. intros a b. zero_or_not b. easy. intros; rewrite Z.div_opp_l_nz; auto. Qed.
Lemma Z_div_zero_opp_r : forall a b:Z, a mod b = 0 -> a/(-b) = -(a/b).
-Proof. intros. zero_or_not b. apply Z.div_opp_r_z; auto. Qed.
+Proof. intros a b ?. zero_or_not b. apply Z.div_opp_r_z; auto. Qed.
Lemma Z_div_nz_opp_r : forall a b:Z, a mod b <> 0 ->
a/(-b) = -(a/b)-1.
@@ -375,19 +375,19 @@ Proof. intros a b. zero_or_not b. easy. intros; rewrite Z.div_opp_r_nz; auto. Qe
Lemma Zdiv_mult_cancel_r : forall a b c:Z,
c <> 0 -> (a*c)/(b*c) = a/b.
-Proof. intros. zero_or_not b. apply Z.div_mul_cancel_r; auto. Qed.
+Proof. intros a b c ?. zero_or_not b. apply Z.div_mul_cancel_r; auto. Qed.
Lemma Zdiv_mult_cancel_l : forall a b c:Z,
c<>0 -> (c*a)/(c*b) = a/b.
Proof.
- intros. rewrite (Z.mul_comm c b); zero_or_not b.
+ intros a b c ?. rewrite (Z.mul_comm c b); zero_or_not b.
rewrite (Z.mul_comm b c). apply Z.div_mul_cancel_l; auto.
Qed.
Lemma Zmult_mod_distr_l: forall a b c,
(c*a) mod (c*b) = c * (a mod b).
Proof.
- intros. zero_or_not c. rewrite (Z.mul_comm c b); zero_or_not b.
+ intros a b c. zero_or_not c. rewrite (Z.mul_comm c b); zero_or_not b.
+ now rewrite Z.mul_0_r.
+ rewrite (Z.mul_comm b c). apply Z.mul_mod_distr_l; auto.
Qed.
@@ -395,7 +395,7 @@ Qed.
Lemma Zmult_mod_distr_r: forall a b c,
(a*c) mod (b*c) = (a mod b) * c.
Proof.
- intros. zero_or_not b. rewrite (Z.mul_comm b c); zero_or_not c.
+ intros a b c. zero_or_not b. rewrite (Z.mul_comm b c); zero_or_not c.
+ now rewrite Z.mul_0_r.
+ rewrite (Z.mul_comm c b). apply Z.mul_mod_distr_r; auto.
Qed.
@@ -403,27 +403,27 @@ Qed.
(** Operations modulo. *)
Theorem Zmod_mod: forall a n, (a mod n) mod n = a mod n.
-Proof. intros. zero_or_not n. apply Z.mod_mod; auto. Qed.
+Proof. intros a n. zero_or_not n. apply Z.mod_mod; auto. Qed.
Theorem Zmult_mod: forall a b n,
(a * b) mod n = ((a mod n) * (b mod n)) mod n.
-Proof. intros. zero_or_not n. apply Z.mul_mod; auto. Qed.
+Proof. intros a b n. zero_or_not n. apply Z.mul_mod; auto. Qed.
Theorem Zplus_mod: forall a b n,
(a + b) mod n = (a mod n + b mod n) mod n.
-Proof. intros. zero_or_not n. apply Z.add_mod; auto. Qed.
+Proof. intros a b n. zero_or_not n. apply Z.add_mod; auto. Qed.
Theorem Zminus_mod: forall a b n,
(a - b) mod n = (a mod n - b mod n) mod n.
Proof.
- intros.
+ intros a b n.
replace (a - b) with (a + (-1) * b); auto with zarith.
replace (a mod n - b mod n) with (a mod n + (-1) * (b mod n)); auto with zarith.
rewrite Zplus_mod.
rewrite Zmult_mod.
- rewrite Zplus_mod with (b:=(-1) * (b mod n)).
+ rewrite (Zplus_mod _ ((-1) * (b mod n))).
rewrite Zmult_mod.
- rewrite Zmult_mod with (b:= b mod n).
+ rewrite (Zmult_mod _ (b mod n)).
repeat rewrite Zmod_mod; auto.
Qed.
@@ -483,17 +483,20 @@ Qed.
Instance Zplus_eqm : Proper (eqm ==> eqm ==> eqm) Z.add.
Proof.
- unfold eqm; repeat red; intros. rewrite Zplus_mod, H, H0, <- Zplus_mod; auto.
+ unfold eqm; repeat red; intros ? ? H ? ? H0.
+ rewrite Zplus_mod, H, H0, <- Zplus_mod; auto.
Qed.
Instance Zminus_eqm : Proper (eqm ==> eqm ==> eqm) Z.sub.
Proof.
- unfold eqm; repeat red; intros. rewrite Zminus_mod, H, H0, <- Zminus_mod; auto.
+ unfold eqm; repeat red; intros ? ? H ? ? H0.
+ rewrite Zminus_mod, H, H0, <- Zminus_mod; auto.
Qed.
Instance Zmult_eqm : Proper (eqm ==> eqm ==> eqm) Z.mul.
Proof.
- unfold eqm; repeat red; intros. rewrite Zmult_mod, H, H0, <- Zmult_mod; auto.
+ unfold eqm; repeat red; intros ? ? H ? ? H0.
+ rewrite Zmult_mod, H, H0, <- Zmult_mod; auto.
Qed.
Instance Zopp_eqm : Proper (eqm ==> eqm) Z.opp.
@@ -503,7 +506,7 @@ Qed.
Lemma Zmod_eqm : forall a, (a mod N) == a.
Proof.
- intros; exact (Zmod_mod a N).
+ intros a; exact (Zmod_mod a N).
Qed.
(* NB: Z.modulo and Z.div are not morphisms with respect to eqm.
@@ -518,7 +521,7 @@ End EqualityModulo.
Lemma Zdiv_Zdiv : forall a b c, 0<=b -> 0<=c -> (a/b)/c = a/(b*c).
Proof.
- intros. zero_or_not b. rewrite Z.mul_comm. zero_or_not c.
+ intros a b c ? ?. zero_or_not b. rewrite Z.mul_comm. zero_or_not c.
rewrite Z.mul_comm. apply Z.div_div; auto.
apply Z.le_neq; auto.
Qed.
@@ -538,7 +541,7 @@ Qed.
Theorem Zdiv_mult_le:
forall a b c, 0<=a -> 0<=b -> 0<=c -> c*(a/b) <= (c*a)/b.
Proof.
- intros. zero_or_not b. now rewrite Z.mul_0_r.
+ intros a b c ? ? ?. zero_or_not b. now rewrite Z.mul_0_r.
apply Z.div_mul_le; auto.
apply Z.le_neq; auto.
Qed.
diff --git a/theories/ZArith/Znat.v b/theories/ZArith/Znat.v
index 6a82645ba6..7f72d42d1f 100644
--- a/theories/ZArith/Znat.v
+++ b/theories/ZArith/Znat.v
@@ -50,7 +50,7 @@ Qed.
Lemma N_nat_Z n : Z.of_nat (N.to_nat n) = Z.of_N n.
Proof.
- destruct n; trivial. simpl.
+ destruct n as [|p]; trivial. simpl.
destruct (Pos2Nat.is_succ p) as (m,H).
rewrite H. simpl. f_equal. now apply SuccNat2Pos.inv.
Qed.
@@ -668,7 +668,7 @@ Qed.
Lemma inj_abs_nat z : Z.of_nat (Z.abs_nat z) = Z.abs z.
Proof.
- destruct z; simpl; trivial;
+ destruct z as [|p|p]; simpl; trivial;
destruct (Pos2Nat.is_succ p) as (n,H); rewrite H; simpl; f_equal;
now apply SuccNat2Pos.inv.
Qed.
diff --git a/theories/ZArith/Znumtheory.v b/theories/ZArith/Znumtheory.v
index 6ba58df721..cad9454906 100644
--- a/theories/ZArith/Znumtheory.v
+++ b/theories/ZArith/Znumtheory.v
@@ -256,15 +256,15 @@ Qed.
Lemma Zis_gcd_for_euclid :
forall a b d q:Z, Zis_gcd b (a - q * b) d -> Zis_gcd a b d.
Proof.
- simple induction 1; constructor; intuition.
+ intros a b d q; simple induction 1; constructor; intuition.
replace a with (a - q * b + q * b). auto with zarith. ring.
Qed.
Lemma Zis_gcd_for_euclid2 :
forall b d q r:Z, Zis_gcd r b d -> Zis_gcd b (b * q + r) d.
Proof.
- simple induction 1; constructor; intuition.
- apply H2; auto.
+ intros b d q r; destruct 1 as [? ? H]; constructor; intuition.
+ apply H; auto.
replace r with (b * q + r - b * q). auto with zarith. ring.
Qed.
@@ -300,9 +300,9 @@ Section extended_euclid_algorithm.
Proof.
intros v3 Hv3; generalize Hv3; pattern v3.
apply Zlt_0_rec.
- clear v3 Hv3; intros.
+ clear v3 Hv3; intros x H ? ? u1 u2 u3 v1 v2 H1 H2 H3.
destruct (Z_zerop x) as [Heq|Hneq].
- apply Euclid_intro with (u := u1) (v := u2) (d := u3).
+ apply (Euclid_intro u1 u2 u3).
assumption.
apply H3.
rewrite Heq; auto with zarith.
@@ -333,12 +333,10 @@ Section extended_euclid_algorithm.
Proof.
case (Z_le_gt_dec 0 b); intro.
intros;
- apply euclid_rec with
- (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := 1) (v3 := b);
+ apply (fun H => euclid_rec b H 1 0 a 0 1);
auto; ring.
intros;
- apply euclid_rec with
- (u1 := 1) (u2 := 0) (u3 := a) (v1 := 0) (v2 := -1) (v3 := - b);
+ apply (fun H => euclid_rec (- b) H 1 0 a 0 (-1));
auto; try ring.
now apply Z.opp_nonneg_nonpos, Z.lt_le_incl, Z.gt_lt.
auto with zarith.
@@ -349,8 +347,8 @@ End extended_euclid_algorithm.
Theorem Zis_gcd_uniqueness_apart_sign :
forall a b d d':Z, Zis_gcd a b d -> Zis_gcd a b d' -> d = d' \/ d = - d'.
Proof.
- simple induction 1.
- intros H1 H2 H3; simple induction 1; intros.
+ intros a b d d'; simple induction 1.
+ intros H1 H2 H3; destruct 1 as [H4 H5 H6].
generalize (H3 d' H4 H5); intro Hd'd.
generalize (H6 d H1 H2); intro Hdd'.
exact (Z.divide_antisym d d' Hdd' Hd'd).
@@ -368,7 +366,7 @@ Proof.
intros a b d Hgcd.
elim (euclid a b); intros u v d0 e g.
generalize (Zis_gcd_uniqueness_apart_sign a b d d0 Hgcd g).
- intro H; elim H; clear H; intros.
+ intro H; elim H; clear H; intros H.
apply Bezout_intro with u v.
rewrite H; assumption.
apply Bezout_intro with (- u) (- v).
@@ -380,7 +378,7 @@ Qed.
Lemma Zis_gcd_mult :
forall a b c d:Z, Zis_gcd a b d -> Zis_gcd (c * a) (c * b) (c * d).
Proof.
- intros a b c d; simple induction 1. constructor; auto with zarith.
+ intros a b c d; intro H; generalize H; simple induction 1. constructor; auto with zarith.
intros x Ha Hb.
elim (Zis_gcd_bezout a b d H). intros u v Huv.
elim Ha; intros a' Ha'.
@@ -407,7 +405,7 @@ Qed.
Lemma bezout_rel_prime : forall a b:Z, Bezout a b 1 -> rel_prime a b.
Proof.
- simple induction 1; constructor; auto with zarith.
+ simple induction 1; intros ? ? H0; constructor; auto with zarith.
intros. rewrite <- H0; auto with zarith.
Qed.
@@ -416,7 +414,7 @@ Qed.
Theorem Gauss : forall a b c:Z, (a | b * c) -> rel_prime a b -> (a | c).
Proof.
- intros. elim (rel_prime_bezout a b H0); intros.
+ intros a b c H H0. elim (rel_prime_bezout a b H0); intros u v H1.
replace c with (c * 1); [ idtac | ring ].
rewrite <- H1.
replace (c * (u * a + v * b)) with (c * u * a + v * (b * c));
@@ -429,11 +427,11 @@ Lemma rel_prime_mult :
forall a b c:Z, rel_prime a b -> rel_prime a c -> rel_prime a (b * c).
Proof.
intros a b c Hb Hc.
- elim (rel_prime_bezout a b Hb); intros.
- elim (rel_prime_bezout a c Hc); intros.
+ elim (rel_prime_bezout a b Hb); intros u v H.
+ elim (rel_prime_bezout a c Hc); intros u0 v0 H0.
apply bezout_rel_prime.
- apply Bezout_intro with
- (u := u * u0 * a + v0 * c * u + u0 * v * b) (v := v * v0).
+ apply (Bezout_intro _ _ _
+ (u * u0 * a + v0 * c * u + u0 * v * b) (v * v0)).
rewrite <- H.
replace (u * a + v * b) with ((u * a + v * b) * 1); [ idtac | ring ].
rewrite <- H0.
@@ -447,7 +445,7 @@ Lemma rel_prime_cross_prod :
Proof.
intros a b c d; intros H H0 H1 H2 H3.
elim (Z.divide_antisym b d).
- - split; auto with zarith.
+ - intros H4; split; auto with zarith.
rewrite H4 in H3.
rewrite Z.mul_comm in H3.
apply Z.mul_reg_l with d; auto.
@@ -473,9 +471,9 @@ Lemma Zis_gcd_rel_prime :
Proof.
intros a b g; intros H H0 H1.
assert (H2 : g <> 0) by
- (intro;
- elim H1; intros;
- elim H4; intros;
+ (intro H2;
+ elim H1; intros ? H4 ?;
+ elim H4; intros ? H6;
rewrite H2 in H6; subst b;
contradict H; rewrite Z.mul_0_r; discriminate).
assert (H3 : g > 0) by
@@ -578,7 +576,7 @@ Lemma prime_divisors :
forall p:Z,
prime p -> forall a:Z, (a | p) -> a = -1 \/ a = 1 \/ a = p \/ a = - p.
Proof.
- destruct 1; intros.
+ intros p; destruct 1 as [H H0]; intros a ?.
assert
(a = - p \/ - p < a < -1 \/ a = -1 \/ a = 0 \/ a = 1 \/ 1 < a < p \/ a = p).
{ assert (Z.abs a <= Z.abs p) as H2.
@@ -602,12 +600,13 @@ Proof.
}
intuition idtac.
(* -p < a < -1 *)
- - absurd (rel_prime (- a) p).
+ - match goal with [hyp : a < -1 |- _] => rename hyp into H4 end.
+ absurd (rel_prime (- a) p).
+ intros [H1p H2p H3p].
assert (- a | - a) by auto with zarith.
- assert (- a | p) by auto with zarith.
+ assert (- a | p) as H5 by auto with zarith.
apply H3p, Z.divide_1_r in H5; auto with zarith.
- destruct H5.
+ destruct H5 as [H5|H5].
* contradict H4; rewrite <- (Z.opp_involutive a), H5 .
apply Z.lt_irrefl.
* contradict H4; rewrite <- (Z.opp_involutive a), H5 .
@@ -616,16 +615,18 @@ Proof.
* now apply Z.opp_le_mono; rewrite Z.opp_involutive; apply Z.lt_le_incl.
* now apply Z.opp_lt_mono; rewrite Z.opp_involutive.
(* a = 0 *)
- - contradict H.
+ - match goal with [hyp : a = 0 |- _] => rename hyp into H2 end.
+ contradict H.
replace p with 0; try discriminate.
now apply sym_equal, Z.divide_0_l; rewrite <-H2.
(* 1 < a < p *)
- - absurd (rel_prime a p).
+ - match goal with [hyp : 1 < a |- _] => rename hyp into H3 end.
+ absurd (rel_prime a p).
+ intros [H1p H2p H3p].
assert (a | a) by auto with zarith.
- assert (a | p) by auto with zarith.
+ assert (a | p) as H5 by auto with zarith.
apply H3p, Z.divide_1_r in H5; auto with zarith.
- destruct H5.
+ destruct H5 as [H5|H5].
* contradict H3; rewrite <- (Z.opp_involutive a), H5 .
apply Z.lt_irrefl.
* contradict H3; rewrite <- (Z.opp_involutive a), H5 .
@@ -639,7 +640,7 @@ Qed.
Lemma prime_rel_prime :
forall p:Z, prime p -> forall a:Z, ~ (p | a) -> rel_prime p a.
Proof.
- intros; constructor; intros; auto with zarith.
+ intros p H a H0; constructor; auto with zarith; intros ? H1 H2.
apply prime_divisors in H1; intuition; subst; auto with zarith.
- absurd (p | a); auto with zarith.
- absurd (p | a); intuition.
@@ -671,7 +672,7 @@ Qed.
Lemma prime_mult :
forall p:Z, prime p -> forall a b:Z, (p | a * b) -> (p | a) \/ (p | b).
Proof.
- intro p; simple induction 1; intros.
+ intro p; simple induction 1; intros ? ? a b ?.
case (Zdivide_dec p a); intuition.
right; apply Gauss with a; auto with zarith.
Qed.
@@ -743,9 +744,9 @@ Proof.
+ now exists 1.
+ elim (H x); auto.
split; trivial.
- apply Z.le_lt_trans with n; try intuition.
+ apply Z.le_lt_trans with n; try tauto.
apply Z.divide_pos_le; auto with zarith.
- apply Z.lt_le_trans with (2 := H0); red; auto.
+ apply Z.lt_le_trans with (2 := proj1 Hn); red; auto.
- (* prime' -> prime *)
constructor; trivial. intros n Hn Hnp.
case (Zis_gcd_unique n p n 1).
@@ -870,7 +871,7 @@ Hint Resolve Z.gcd_0_r Z.gcd_1_r : zarith.
Theorem Zgcd_1_rel_prime : forall a b,
Z.gcd a b = 1 <-> rel_prime a b.
Proof.
- unfold rel_prime; split; intro H.
+ unfold rel_prime; intros a b; split; intro H.
rewrite <- H; apply Zgcd_is_gcd.
case (Zis_gcd_unique a b (Z.gcd a b) 1); auto.
apply Zgcd_is_gcd.
@@ -894,10 +895,10 @@ Definition prime_dec_aux:
Proof.
intros p m.
case (Z_lt_dec 1 m); intros H1;
- [ | left; intros; exfalso;
+ [ | left; intros n ?; exfalso;
contradict H1; apply Z.lt_trans with n; intuition].
pattern m; apply natlike_rec; auto with zarith.
- - left; intros; exfalso.
+ - left; intros n ?; exfalso.
absurd (1 < 0); try discriminate.
apply Z.lt_trans with n; intuition.
- intros x Hx IH; destruct IH as [F|E].
diff --git a/theories/ZArith/Zorder.v b/theories/ZArith/Zorder.v
index 7e33fe2b4c..949a01860f 100644
--- a/theories/ZArith/Zorder.v
+++ b/theories/ZArith/Zorder.v
@@ -354,7 +354,7 @@ Qed.
Lemma Zle_0_nat : forall n:nat, 0 <= Z.of_nat n.
Proof.
- induction n; simpl; intros. apply Z.le_refl. easy.
+ intros n; induction n; simpl; intros. apply Z.le_refl. easy.
Qed.
Hint Immediate Z.eq_le_incl: zarith.
diff --git a/theories/ZArith/Zpow_def.v b/theories/ZArith/Zpow_def.v
index 8609a6af98..d4f58c3b04 100644
--- a/theories/ZArith/Zpow_def.v
+++ b/theories/ZArith/Zpow_def.v
@@ -25,9 +25,9 @@ Notation Zpower_Ppow := Pos2Z.inj_pow (only parsing).
Lemma Zpower_theory : power_theory 1 Z.mul (@eq Z) Z.of_N Z.pow.
Proof.
- constructor. intros.
- destruct n;simpl;trivial.
+ constructor. intros z n.
+ destruct n as [|p];simpl;trivial.
unfold Z.pow_pos.
rewrite <- (Z.mul_1_r (pow_pos _ _ _)). generalize 1.
- induction p; simpl; intros; rewrite ?IHp, ?Z.mul_assoc; trivial.
+ induction p as [p IHp|p IHp|]; simpl; intros; rewrite ?IHp, ?Z.mul_assoc; trivial.
Qed.
diff --git a/theories/dune b/theories/dune
index c2d8197ee4..18e000cfe1 100644
--- a/theories/dune
+++ b/theories/dune
@@ -14,10 +14,8 @@
coq.plugins.cc
coq.plugins.firstorder
- coq.plugins.numeral_notation
- coq.plugins.string_notation
+ coq.plugins.number_string_notation
coq.plugins.int63_syntax
- coq.plugins.r_syntax
coq.plugins.float_syntax
coq.plugins.btauto
diff --git a/theories/micromega/EnvRing.v b/theories/micromega/EnvRing.v
index 7bef11e89a..bb21472e57 100644
--- a/theories/micromega/EnvRing.v
+++ b/theories/micromega/EnvRing.v
@@ -557,7 +557,8 @@ Section MakeRingPol.
Lemma Peq_ok P P' : (P ?== P') = true -> forall l, P@l == P'@ l.
Proof.
- revert P';induction P;destruct P';simpl; intros H l; try easy.
+ revert P';induction P as [|p P IHP|P2 IHP1 p P3 IHP2];
+ intro P';destruct P' as [|p0 P'|P'1 p0 P'2];simpl; intros H l; try easy.
- now apply (morph_eq CRmorph).
- destruct (Pos.compare_spec p p0); [ subst | easy | easy ].
now rewrite IHP.
@@ -587,7 +588,7 @@ Section MakeRingPol.
Lemma env_morph p e1 e2 :
(forall x, e1 x = e2 x) -> p @ e1 = p @ e2.
Proof.
- revert e1 e2. induction p ; simpl.
+ revert e1 e2. induction p as [|? ? IHp|? IHp1 ? ? IHp2]; simpl.
- reflexivity.
- intros e1 e2 EQ. apply IHp. intros. apply EQ.
- intros e1 e2 EQ. f_equal; [f_equal|].
@@ -664,13 +665,13 @@ Qed.
Lemma PaddC_ok c P l : (PaddC P c)@l == P@l + [c].
Proof.
- revert l;induction P;simpl;intros;Esimpl;trivial.
+ revert l;induction P as [| |? ? ? ? IHP2];simpl;intros;Esimpl;trivial.
rewrite IHP2;rsimpl.
Qed.
Lemma PsubC_ok c P l : (PsubC P c)@l == P@l - [c].
Proof.
- revert l;induction P;simpl;intros.
+ revert l;induction P as [|? ? IHP|? ? ? ? IHP2];simpl;intros.
- Esimpl.
- rewrite IHP;rsimpl.
- rewrite IHP2;rsimpl.
@@ -678,7 +679,7 @@ Qed.
Lemma PmulC_aux_ok c P l : (PmulC_aux P c)@l == P@l * [c].
Proof.
- revert l;induction P;simpl;intros;Esimpl;trivial.
+ revert l;induction P as [| |? IHP1 ? ? IHP2];simpl;intros;Esimpl;trivial.
rewrite IHP1, IHP2;rsimpl. add_permut. mul_permut.
Qed.
@@ -694,7 +695,7 @@ Qed.
Lemma Popp_ok P l : (--P)@l == - P@l.
Proof.
- revert l;induction P;simpl;intros.
+ revert l;induction P as [|? ? IHP|? IHP1 ? ? IHP2];simpl;intros.
- Esimpl.
- apply IHP.
- rewrite IHP1, IHP2;rsimpl.
@@ -707,7 +708,7 @@ Qed.
(PaddX Padd P' k P) @ l == P@l + P'@l * (hd l)^k.
Proof.
intros IHP'.
- revert k l. induction P;simpl;intros.
+ revert k l. induction P as [|p|? IHP1];simpl;intros.
- add_permut.
- destruct p; simpl;
rewrite ?Pjump_xO_tail, ?Pjump_pred_double; add_permut.
@@ -719,8 +720,8 @@ Qed.
Lemma Padd_ok P' P l : (P ++ P')@l == P@l + P'@l.
Proof.
- revert P l; induction P';simpl;intros;Esimpl.
- - revert p l; induction P;simpl;intros.
+ revert P l; induction P' as [|p P' IHP'|? IHP'1 ? ? IHP'2];simpl;intros P l;Esimpl.
+ - revert p l; induction P as [|? P IHP|? IHP1 p ? IHP2];simpl;intros p0 l.
+ Esimpl; add_permut.
+ destr_pos_sub; intros ->;Esimpl.
* now rewrite IHP'.
@@ -730,7 +731,7 @@ Qed.
* rewrite IHP2;simpl. rsimpl. rewrite Pjump_xO_tail. Esimpl.
* rewrite IHP2;simpl. rewrite Pjump_pred_double. rsimpl.
* rewrite IHP'. rsimpl.
- - destruct P;simpl.
+ - destruct P as [|p0|];simpl.
+ Esimpl. add_permut.
+ destruct p0;simpl;Esimpl; rewrite IHP'2; simpl.
* rewrite Pjump_xO_tail. rsimpl. add_permut.
@@ -749,7 +750,7 @@ Qed.
(PsubX Psub P' k P) @ l == P@l - P'@l * (hd l)^k.
Proof.
intros IHP'.
- revert k l. induction P;simpl;intros.
+ revert k l. induction P as [|p|? IHP1];simpl;intros.
- rewrite Popp_ok;rsimpl; add_permut.
- destruct p; simpl;
rewrite Popp_ok;rsimpl;
@@ -762,8 +763,8 @@ Qed.
Lemma Psub_ok P' P l : (P -- P')@l == P@l - P'@l.
Proof.
- revert P l; induction P';simpl;intros;Esimpl.
- - revert p l; induction P;simpl;intros.
+ revert P l; induction P' as [|p P' IHP'|? IHP'1 ? ? IHP'2];simpl;intros P l;Esimpl.
+ - revert p l; induction P as [|? ? IHP|? IHP1 ? ? IHP2];simpl;intros p0 l.
+ Esimpl; add_permut.
+ destr_pos_sub; intros ->;Esimpl.
* rewrite IHP';rsimpl.
@@ -773,7 +774,7 @@ Qed.
* rewrite IHP2;simpl. rsimpl. rewrite Pjump_xO_tail. Esimpl.
* rewrite IHP2;simpl. rewrite Pjump_pred_double. rsimpl.
* rewrite IHP'. rsimpl.
- - destruct P;simpl.
+ - destruct P as [|p0|];simpl.
+ Esimpl; add_permut.
+ destruct p0;simpl;Esimpl; rewrite IHP'2; simpl.
* rewrite Pjump_xO_tail. rsimpl. add_permut.
@@ -791,8 +792,8 @@ Qed.
(forall P l, (Pmul P P') @ l == P @ l * P' @ l) ->
forall P p l, (PmulI Pmul P' p P) @ l == P @ l * P' @ (jump p l).
Proof.
- intros IHP'.
- induction P;simpl;intros.
+ intros IHP' P.
+ induction P as [|? ? IHP|? IHP1 ? ? IHP2];simpl;intros p0 l.
- Esimpl; mul_permut.
- destr_pos_sub; intros ->;Esimpl.
+ now rewrite IHP'.
@@ -806,10 +807,10 @@ Qed.
Lemma Pmul_ok P P' l : (P**P')@l == P@l * P'@l.
Proof.
- revert P l;induction P';simpl;intros.
+ revert P l;induction P' as [| |? IHP'1 ? ? IHP'2];simpl;intros P l.
- apply PmulC_ok.
- apply PmulI_ok;trivial.
- - destruct P.
+ - destruct P as [|p0|].
+ rewrite (ARmul_comm ARth). Esimpl.
+ Esimpl. rewrite IHP'1;Esimpl. f_equiv.
destruct p0;rewrite IHP'2;Esimpl.
@@ -823,7 +824,7 @@ Qed.
Lemma Psquare_ok P l : (Psquare P)@l == P@l * P@l.
Proof.
- revert l;induction P;simpl;intros;Esimpl.
+ revert l;induction P as [|? ? IHP|P2 IHP1 p ? IHP2];simpl;intros l;Esimpl.
- apply IHP.
- rewrite Padd_ok, Pmul_ok;Esimpl.
rewrite IHP1, IHP2.
@@ -833,7 +834,7 @@ Qed.
Lemma Mphi_morph M e1 e2 :
(forall x, e1 x = e2 x) -> M @@ e1 = M @@ e2.
Proof.
- revert e1 e2; induction M; simpl; intros e1 e2 EQ; trivial.
+ revert e1 e2; induction M as [|? ? IHM|? ? IHM]; simpl; intros e1 e2 EQ; trivial.
- apply IHM. intros; apply EQ.
- f_equal.
* apply IHM. intros; apply EQ.
@@ -890,7 +891,8 @@ Qed.
let (Q,R) := MFactor P M in
P@l == Q@l + M@@l * R@l.
Proof.
- revert M l; induction P; destruct M; intros l; simpl; auto; Esimpl.
+ revert M l; induction P as [|? ? IHP|? IHP1 ? ? IHP2];
+ intros M; destruct M; intros l; simpl; auto; Esimpl.
- case Pos.compare_spec; intros He; simpl.
* destr_mfactor R1 S1. now rewrite IHP, He, !mkPinj_ok.
* destr_mfactor R1 S1. rewrite IHP; simpl.
@@ -922,7 +924,7 @@ Qed.
Lemma PNSubst1_ok n P1 M1 P2 l :
M1@@l == P2@l -> P1@l == (PNSubst1 P1 M1 P2 n)@l.
Proof.
- revert P1. induction n; simpl; intros P1;
+ revert P1. induction n as [|n IHn]; simpl; intros P1;
generalize (POneSubst_ok P1 M1 P2); destruct POneSubst;
intros; rewrite <- ?IHn; auto; reflexivity.
Qed.
@@ -953,7 +955,7 @@ Qed.
Lemma PSubstL_ok n LM1 P1 P2 l :
PSubstL P1 LM1 n = Some P2 -> MPcond LM1 l -> P1@l == P2@l.
Proof.
- revert P1. induction LM1 as [|(M2,P2') LM2 IH]; simpl; intros.
+ revert P1. induction LM1 as [|(M2,P2') LM2 IH]; simpl; intros P3 H **.
- discriminate.
- assert (H':=PNSubst_ok n P3 M2 P2'). destruct PNSubst.
* injection H as [= <-]. rewrite <- PSubstL1_ok; intuition.
@@ -963,7 +965,7 @@ Qed.
Lemma PNSubstL_ok m n LM1 P1 l :
MPcond LM1 l -> P1@l == (PNSubstL P1 LM1 m n)@l.
Proof.
- revert LM1 P1. induction m; simpl; intros;
+ revert LM1 P1. induction m as [|m IHm]; simpl; intros LM1 P2 **;
assert (H' := PSubstL_ok n LM1 P2); destruct PSubstL;
auto; try reflexivity.
rewrite <- IHm; auto.
@@ -1017,7 +1019,7 @@ Section POWER.
forall res P p, (Ppow_pos res P p)@l == res@l * (pow_pos Pmul P p)@l.
Proof.
intros subst_l_ok res P p. revert res.
- induction p;simpl;intros; rewrite ?subst_l_ok, ?Pmul_ok, ?IHp;
+ induction p as [p IHp|p IHp|];simpl;intros; rewrite ?subst_l_ok, ?Pmul_ok, ?IHp;
mul_permut.
Qed.
@@ -1025,7 +1027,7 @@ Section POWER.
(forall P, subst_l P@l == P@l) ->
forall P n, (Ppow_N P n)@l == (pow_N P1 Pmul P n)@l.
Proof.
- destruct n;simpl.
+ intros ? P n;destruct n;simpl.
- reflexivity.
- rewrite Ppow_pos_ok by trivial. Esimpl.
Qed.
@@ -1092,7 +1094,7 @@ Section POWER.
PEeval l pe == (norm_aux pe)@l.
Proof.
intros.
- induction pe.
+ induction pe as [| |pe1 IHpe1 pe2 IHpe2|? IHpe1 ? IHpe2|? IHpe1 ? IHpe2|? IHpe|? IHpe n0].
- reflexivity.
- apply mkX_ok.
- simpl PEeval. rewrite IHpe1, IHpe2.
@@ -1104,8 +1106,8 @@ Section POWER.
- simpl. rewrite IHpe1, IHpe2. now rewrite Pmul_ok.
- simpl. rewrite IHpe. Esimpl.
- simpl. rewrite Ppow_N_ok by reflexivity.
- rewrite (rpow_pow_N pow_th). destruct n0; simpl; Esimpl.
- induction p;simpl; now rewrite ?IHp, ?IHpe, ?Pms_ok, ?Pmul_ok.
+ rewrite (rpow_pow_N pow_th). destruct n0 as [|p]; simpl; Esimpl.
+ induction p as [p IHp|p IHp|];simpl; now rewrite ?IHp, ?IHpe, ?Pms_ok, ?Pmul_ok.
Qed.
End NORM_SUBST_REC.
diff --git a/theories/micromega/OrderedRing.v b/theories/micromega/OrderedRing.v
index ea9b20847b..5fa3740ab1 100644
--- a/theories/micromega/OrderedRing.v
+++ b/theories/micromega/OrderedRing.v
@@ -235,13 +235,13 @@ Qed.
Theorem Rle_lt_trans : forall n m p : R, n <= m -> m < p -> n < p.
Proof.
intros n m p H1 H2; le_elim H1.
-now apply Rlt_trans with (m := m). now rewrite H1.
+now apply (Rlt_trans (m := m)). now rewrite H1.
Qed.
Theorem Rlt_le_trans : forall n m p : R, n < m -> m <= p -> n < p.
Proof.
intros n m p H1 H2; le_elim H2.
-now apply Rlt_trans with (m := m). now rewrite <- H2.
+now apply (Rlt_trans (m := m)). now rewrite <- H2.
Qed.
Theorem Rle_gt_cases : forall n m : R, n <= m \/ m < n.
diff --git a/theories/micromega/Refl.v b/theories/micromega/Refl.v
index 1189309af1..0f82f9e578 100644
--- a/theories/micromega/Refl.v
+++ b/theories/micromega/Refl.v
@@ -31,7 +31,7 @@ Fixpoint make_impl (A : Type) (eval : A -> Prop) (l : list A) (goal : Prop) {str
Theorem make_impl_true :
forall (A : Type) (eval : A -> Prop) (l : list A), make_impl eval l True.
Proof.
-induction l as [| a l IH]; simpl.
+intros A eval l; induction l as [| a l IH]; simpl.
trivial.
intro; apply IH.
Qed.
@@ -42,9 +42,9 @@ Theorem make_impl_map :
(EVAL : forall x, eval' x <-> eval (fst x)),
make_impl eval' l r <-> make_impl eval (List.map fst l) r.
Proof.
-induction l as [| a l IH]; simpl.
+intros A B eval eval' l; induction l as [| a l IH]; simpl.
- tauto.
-- intros.
+- intros r EVAL.
rewrite EVAL.
rewrite IH.
tauto.
@@ -61,18 +61,18 @@ Fixpoint make_conj (A : Type) (eval : A -> Prop) (l : list A) {struct l} : Prop
Theorem make_conj_cons : forall (A : Type) (eval : A -> Prop) (a : A) (l : list A),
make_conj eval (a :: l) <-> eval a /\ make_conj eval l.
Proof.
-intros; destruct l; simpl; tauto.
+intros A eval a l; destruct l; simpl; tauto.
Qed.
Lemma make_conj_impl : forall (A : Type) (eval : A -> Prop) (l : list A) (g : Prop),
(make_conj eval l -> g) <-> make_impl eval l g.
Proof.
- induction l.
+ intros A eval l; induction l as [|? l IHl].
simpl.
tauto.
simpl.
- intros.
+ intros g.
destruct l.
simpl.
tauto.
@@ -83,11 +83,11 @@ Qed.
Lemma make_conj_in : forall (A : Type) (eval : A -> Prop) (l : list A),
make_conj eval l -> (forall p, In p l -> eval p).
Proof.
- induction l.
+ intros A eval l; induction l as [|? l IHl].
simpl.
tauto.
simpl.
- intros.
+ intros H ? H0.
destruct l.
simpl in H0.
destruct H0.
@@ -101,10 +101,10 @@ Qed.
Lemma make_conj_app : forall A eval l1 l2, @make_conj A eval (l1 ++ l2) <-> @make_conj A eval l1 /\ @make_conj A eval l2.
Proof.
- induction l1.
+ intros A eval l1; induction l1 as [|a l1 IHl1].
simpl.
tauto.
- intros.
+ intros l2.
change ((a::l1) ++ l2) with (a :: (l1 ++ l2)).
rewrite make_conj_cons.
rewrite IHl1.
@@ -116,7 +116,7 @@ Infix "+++" := rev_append (right associativity, at level 60) : list_scope.
Lemma make_conj_rapp : forall A eval l1 l2, @make_conj A eval (l1 +++ l2) <-> @make_conj A eval (l1++l2).
Proof.
- induction l1.
+ intros A eval l1; induction l1 as [|? ? IHl1].
- simpl. tauto.
- intros.
simpl rev_append at 1.
@@ -141,10 +141,10 @@ Lemma not_make_conj_app : forall (A:Type) (t:list A) a eval
(no_middle_eval : forall d, eval d \/ ~ eval d) ,
~ make_conj eval (t ++ a) <-> (~ make_conj eval t) \/ (~ make_conj eval a).
Proof.
- induction t.
+ intros A t; induction t as [|a t IHt].
- simpl.
tauto.
- - intros.
+ - intros a0 **.
simpl ((a::t)++a0).
rewrite !not_make_conj_cons by auto.
rewrite IHt by auto.
diff --git a/theories/micromega/RingMicromega.v b/theories/micromega/RingMicromega.v
index f7a848d7a5..b5289b5800 100644
--- a/theories/micromega/RingMicromega.v
+++ b/theories/micromega/RingMicromega.v
@@ -215,7 +215,7 @@ Lemma OpMult_sound :
forall (o o' om: Op1) (x y : R),
eval_op1 o x -> eval_op1 o' y -> OpMult o o' = Some om -> eval_op1 om (x * y).
Proof.
-unfold eval_op1; destruct o; simpl; intros o' om x y H1 H2 H3.
+unfold eval_op1; intros o; destruct o; simpl; intros o' om x y H1 H2 H3.
(* x == 0 *)
inversion H3. rewrite H1. now rewrite (Rtimes_0_l sor).
(* x ~= 0 *)
@@ -246,9 +246,9 @@ Lemma OpAdd_sound :
forall (o o' oa : Op1) (e e' : R),
eval_op1 o e -> eval_op1 o' e' -> OpAdd o o' = Some oa -> eval_op1 oa (e + e').
Proof.
-unfold eval_op1; destruct o; simpl; intros o' oa e e' H1 H2 Hoa.
+unfold eval_op1; intros o; destruct o; simpl; intros o' oa e e' H1 H2 Hoa.
(* e == 0 *)
-inversion Hoa. rewrite <- H0.
+inversion Hoa as [H0]. rewrite <- H0.
destruct o' ; rewrite H1 ; now rewrite (Rplus_0_l sor).
(* e ~= 0 *)
destruct o'.
@@ -373,8 +373,8 @@ Lemma pexpr_times_nformula_correct : forall (env: PolEnv) (e: PolC) (f f' : NFor
eval_nformula env f'.
Proof.
unfold pexpr_times_nformula.
- destruct f.
- intros. destruct o ; inversion H0 ; try discriminate.
+ intros env e f; destruct f as [? o].
+ intros f' H H0. destruct o ; inversion H0 ; try discriminate.
simpl in *. unfold eval_pol in *.
rewrite (Pmul_ok (SORsetoid sor) Rops_wd
(Rth_ARth (SORsetoid sor) Rops_wd (SORrt sor)) (SORrm addon)).
@@ -388,9 +388,9 @@ Lemma nformula_times_nformula_correct : forall (env:PolEnv)
eval_nformula env f.
Proof.
unfold nformula_times_nformula.
- destruct f1 ; destruct f2.
+ intros env f1 f2; destruct f1 as [? o]; destruct f2 as [? o0].
case_eq (OpMult o o0) ; simpl ; try discriminate.
- intros. inversion H2 ; simpl.
+ intros o1 H ? H0 H1 H2. inversion H2 ; simpl.
unfold eval_pol.
destruct o1; simpl;
rewrite (Pmul_ok (SORsetoid sor) Rops_wd
@@ -405,9 +405,9 @@ Lemma nformula_plus_nformula_correct : forall (env:PolEnv)
eval_nformula env f.
Proof.
unfold nformula_plus_nformula.
- destruct f1 ; destruct f2.
+ intros env f1 f2; destruct f1 as [? o] ; destruct f2 as [? o0].
case_eq (OpAdd o o0) ; simpl ; try discriminate.
- intros. inversion H2 ; simpl.
+ intros o1 H ? H0 H1 H2. inversion H2 ; simpl.
unfold eval_pol.
destruct o1; simpl;
rewrite (Padd_ok (SORsetoid sor) Rops_wd
@@ -421,9 +421,10 @@ Lemma eval_Psatz_Sound :
forall (e : Psatz) (f : NFormula), eval_Psatz l e = Some f ->
eval_nformula env f.
Proof.
- induction e.
+ intros l env H e;
+ induction e as [n|?|? e IHe|e1 IHe1 e2 IHe2|e1 IHe1 e2 IHe2|c|].
(* PsatzIn *)
- simpl ; intros.
+ simpl ; intros f H0.
destruct (nth_in_or_default n l (Pc cO, Equal)) as [Hin|Heq].
(* index is in bounds *)
apply H. congruence.
@@ -432,7 +433,7 @@ Proof.
rewrite Heq. simpl.
now apply (morph0 (SORrm addon)).
(* PsatzSquare *)
- simpl. intros. inversion H0.
+ simpl. intros ? H0. inversion H0.
simpl. unfold eval_pol.
rewrite (Psquare_ok (SORsetoid sor) Rops_wd
(Rth_ARth (SORsetoid sor) Rops_wd (SORrt sor)) (SORrm addon));
@@ -440,7 +441,7 @@ Proof.
(* PsatzMulC *)
simpl.
intro.
- case_eq (eval_Psatz l e) ; simpl ; intros.
+ case_eq (eval_Psatz l e) ; simpl ; intros ? H0; [intros H1|].
apply IHe in H0.
apply pexpr_times_nformula_correct with (1:=H0) (2:= H1).
discriminate.
@@ -448,24 +449,24 @@ Proof.
simpl ; intro.
case_eq (eval_Psatz l e1) ; simpl ; try discriminate.
case_eq (eval_Psatz l e2) ; simpl ; try discriminate.
- intros.
+ intros n H0 n0 H1 ?.
apply IHe1 in H1. apply IHe2 in H0.
apply (nformula_times_nformula_correct env n0 n) ; assumption.
(* PsatzAdd *)
simpl ; intro.
case_eq (eval_Psatz l e1) ; simpl ; try discriminate.
case_eq (eval_Psatz l e2) ; simpl ; try discriminate.
- intros.
+ intros n H0 n0 H1 ?.
apply IHe1 in H1. apply IHe2 in H0.
apply (nformula_plus_nformula_correct env n0 n) ; assumption.
(* PsatzC *)
simpl.
intro. case_eq (cO [<] c).
- intros. inversion H1. simpl.
+ intros H0 H1. inversion H1. simpl.
rewrite <- (morph0 (SORrm addon)). now apply cltb_sound.
discriminate.
(* PsatzZ *)
- simpl. intros. inversion H0.
+ simpl. intros ? H0. inversion H0.
simpl. apply (morph0 (SORrm addon)).
Qed.
@@ -484,7 +485,8 @@ Fixpoint ge_bool (n m : nat) : bool :=
Lemma ge_bool_cases : forall n m,
(if ge_bool n m then n >= m else n < m)%nat.
Proof.
- induction n; destruct m ; simpl; auto with arith.
+ intros n; induction n as [|n IHn];
+ intros m; destruct m as [|m]; simpl; auto with arith.
specialize (IHn m). destruct (ge_bool); auto with arith.
Qed.
@@ -511,26 +513,27 @@ Fixpoint extract_hyps (l: list NFormula) (ln : list nat) : list NFormula :=
| nil => nil
| n::ln => nth n l (Pc cO, Equal) :: extract_hyps l ln
end.
-
+
Lemma extract_hyps_app : forall l ln1 ln2,
extract_hyps l (ln1 ++ ln2) = (extract_hyps l ln1) ++ (extract_hyps l ln2).
Proof.
- induction ln1.
+ intros l ln1; induction ln1 as [|? ln1 IHln1].
reflexivity.
simpl.
intros.
rewrite IHln1. reflexivity.
Qed.
-
+
Ltac inv H := inversion H ; try subst ; clear H.
Lemma nhyps_of_psatz_correct : forall (env : PolEnv) (e:Psatz) (l : list NFormula) (f: NFormula),
- eval_Psatz l e = Some f ->
+ eval_Psatz l e = Some f ->
((forall f', In f' (extract_hyps l (nhyps_of_psatz e)) -> eval_nformula env f') -> eval_nformula env f).
Proof.
- induction e ; intros.
+ intros env e; induction e as [n|?|? e IHe|e1 IHe1 e2 IHe2|e1 IHe1 e2 IHe2|c|];
+ intros l f H H0.
(*PsatzIn*)
- simpl in *.
+ simpl in *.
apply H0. intuition congruence.
(* PsatzSquare *)
simpl in *.
@@ -543,15 +546,15 @@ Proof.
(* PsatzMulC *)
simpl in *.
case_eq (eval_Psatz l e).
- intros. rewrite H1 in H. simpl in H.
+ intros ? H1. rewrite H1 in H. simpl in H.
apply pexpr_times_nformula_correct with (2:= H).
apply IHe with (1:= H1); auto.
- intros. rewrite H1 in H. simpl in H ; discriminate.
+ intros H1. rewrite H1 in H. simpl in H ; discriminate.
(* PsatzMulE *)
simpl in *.
revert H.
case_eq (eval_Psatz l e1).
- case_eq (eval_Psatz l e2) ; simpl ; intros.
+ case_eq (eval_Psatz l e2) ; simpl ; intros ? H ? H1; [intros H2|].
apply nformula_times_nformula_correct with (3:= H2).
apply IHe1 with (1:= H1) ; auto.
intros. apply H0. rewrite extract_hyps_app.
@@ -564,7 +567,7 @@ Proof.
simpl in *.
revert H.
case_eq (eval_Psatz l e1).
- case_eq (eval_Psatz l e2) ; simpl ; intros.
+ case_eq (eval_Psatz l e2) ; simpl ; intros ? H ? H1; [intros H2|].
apply nformula_plus_nformula_correct with (3:= H2).
apply IHe1 with (1:= H1) ; auto.
intros. apply H0. rewrite extract_hyps_app.
@@ -576,16 +579,16 @@ Proof.
(* PsatzC *)
simpl in H.
case_eq (cO [<] c).
- intros. rewrite H1 in H. inv H.
+ intros H1. rewrite H1 in H. inv H.
unfold eval_nformula. simpl.
rewrite <- (morph0 (SORrm addon)). now apply cltb_sound.
- intros. rewrite H1 in H. discriminate.
+ intros H1. rewrite H1 in H. discriminate.
(* PsatzZ *)
simpl in *. inv H.
unfold eval_nformula. simpl.
apply (morph0 (SORrm addon)).
Qed.
-
+
@@ -663,8 +666,8 @@ intros l cm H env.
unfold check_normalised_formulas in H.
revert H.
case_eq (eval_Psatz l cm) ; [|discriminate].
-intros nf. intros.
-rewrite <- make_conj_impl. intro.
+intros nf. intros H H0.
+rewrite <- make_conj_impl. intro H1.
assert (H1' := make_conj_in _ _ H1).
assert (Hnf := @eval_Psatz_Sound _ _ H1' _ _ H).
destruct nf.
@@ -861,7 +864,7 @@ Proof.
set (F := (fun (x : NFormula) (acc : list (list (NFormula * T))) =>
if check_inconsistent x then acc else ((x, tg) :: nil) :: acc)).
set (G := ((fun x : NFormula => eval_nformula env x -> False))).
- induction l.
+ induction l as [|a l IHl].
- compute.
tauto.
- rewrite make_conj_cons.
@@ -896,13 +899,13 @@ Definition cnf_negate {T: Type} (t: Formula C) (tg: T) : cnf NFormula T :=
Lemma eq0_cnf : forall x,
(0 < x -> False) /\ (0 < - x -> False) <-> x == 0.
Proof.
- split ; intros.
+ intros x; split ; intros H.
+ apply (SORle_antisymm sor).
* now rewrite (Rle_ngt sor).
* rewrite (Rle_ngt sor). rewrite (Rlt_lt_minus sor).
setoid_replace (0 - x) with (-x) by ring.
tauto.
- + split; intro.
+ + split; intro H0.
* rewrite (SORlt_le_neq sor) in H0.
apply (proj2 H0).
now rewrite H.
@@ -918,7 +921,7 @@ Proof.
destruct f as [e o]; destruct o eqn:Op; cbn - [psub];
repeat rewrite eval_pol_sub; fold eval_pol; repeat rewrite eval_pol_Pc;
repeat rewrite eval_pol_opp;
- generalize (eval_pol env e) as x; intro.
+ generalize (eval_pol env e) as x; intro x.
- apply eq0_cnf.
- unfold not. tauto.
- symmetry. rewrite (Rlt_nge sor).
@@ -955,7 +958,7 @@ Proof.
intros T env t tg.
unfold cnf_normalise.
rewrite normalise_sound.
- generalize (normalise t) as f;intro.
+ generalize (normalise t) as f;intro f.
destruct (check_inconsistent f) eqn:U.
- destruct f as [e op].
assert (US := check_inconsistent_sound _ _ U env).
@@ -970,7 +973,7 @@ Proof.
intros T env t tg.
rewrite normalise_sound.
unfold cnf_negate.
- generalize (normalise t) as f;intro.
+ generalize (normalise t) as f;intro f.
destruct (check_inconsistent f) eqn:U.
-
destruct f as [e o].
@@ -983,9 +986,9 @@ Qed.
Lemma eval_nformula_dec : forall env d, (eval_nformula env d) \/ ~ (eval_nformula env d).
Proof.
- intros.
- destruct d ; simpl.
- generalize (eval_pol env p); intros.
+ intros env d.
+ destruct d as [p o]; simpl.
+ generalize (eval_pol env p); intros r.
destruct o ; simpl.
apply (Req_em sor r 0).
destruct (Req_em sor r 0) ; tauto.
@@ -1008,7 +1011,7 @@ Lemma xdenorm_correct : forall p i env,
eval_pol (jump i env) p == eval_pexpr env (xdenorm (Pos.succ i) p).
Proof.
unfold eval_pol.
- induction p.
+ intros p; induction p as [|? p IHp|p2 IHp1 ? p3 IHp2].
simpl. reflexivity.
(* Pinj *)
simpl.
@@ -1037,7 +1040,7 @@ Definition denorm := xdenorm xH.
Lemma denorm_correct : forall p env, eval_pol env p == eval_pexpr env (denorm p).
Proof.
unfold denorm.
- induction p.
+ intros p; induction p as [| |? IHp1 ? ? IHp2].
reflexivity.
simpl.
rewrite Pos.add_1_r.
@@ -1092,7 +1095,9 @@ Definition eval_sformula (env : PolEnv) (f : Formula S) : Prop :=
Lemma eval_pexprSC : forall env s, eval_sexpr env s = eval_pexpr env (map_PExpr s).
Proof.
unfold eval_pexpr, eval_sexpr.
- induction s ; simpl ; try (rewrite IHs1 ; rewrite IHs2) ; try reflexivity.
+ intros env s;
+ induction s as [| |? IHs1 ? IHs2|? IHs1 ? IHs2|? IHs1 ? IHs2|? IHs|? IHs ?];
+ simpl ; try (rewrite IHs1 ; rewrite IHs2) ; try reflexivity.
apply phi_C_of_S.
rewrite IHs. reflexivity.
rewrite IHs. reflexivity.
@@ -1101,7 +1106,7 @@ Qed.
(** equality might be (too) strong *)
Lemma eval_formulaSC : forall env f, eval_sformula env f = eval_formula env (map_Formula f).
Proof.
- destruct f.
+ intros env f; destruct f.
simpl.
repeat rewrite eval_pexprSC.
reflexivity.
diff --git a/theories/micromega/Tauto.v b/theories/micromega/Tauto.v
index dddced5739..99af214396 100644
--- a/theories/micromega/Tauto.v
+++ b/theories/micromega/Tauto.v
@@ -185,7 +185,7 @@ Section S.
| EQ f1 f2 => (eval_f f1) = (eval_f f2)
end.
Proof.
- destruct f ; reflexivity.
+ intros k f; destruct f ; reflexivity.
Qed.
End EVAL.
@@ -197,23 +197,23 @@ Section S.
Definition eiff (k: kind) : rtyp k -> rtyp k -> Prop :=
if k as k' return rtyp k' -> rtyp k' -> Prop then iff else @eq bool.
- Lemma eiff_refl : forall (k: kind) (x : rtyp k),
+ Lemma eiff_refl (k: kind) (x : rtyp k) :
eiff k x x.
Proof.
destruct k ; simpl; tauto.
Qed.
- Lemma eiff_sym : forall k (x y : rtyp k), eiff k x y -> eiff k y x.
+ Lemma eiff_sym k (x y : rtyp k) : eiff k x y -> eiff k y x.
Proof.
destruct k ; simpl; intros ; intuition.
Qed.
- Lemma eiff_trans : forall k (x y z : rtyp k), eiff k x y -> eiff k y z -> eiff k x z.
+ Lemma eiff_trans k (x y z : rtyp k) : eiff k x y -> eiff k y z -> eiff k x z.
Proof.
destruct k ; simpl; intros ; intuition congruence.
Qed.
- Lemma hold_eiff : forall (k: kind) (x y : rtyp k),
+ Lemma hold_eiff (k: kind) (x y : rtyp k) :
(hold k x <-> hold k y) <-> eiff k x y.
Proof.
destruct k ; simpl.
@@ -266,7 +266,10 @@ Section S.
forall (k: kind)(f : GFormula k),
(eiff k (eval_f ev f) (eval_f ev' f)).
Proof.
- induction f ; simpl.
+ intros ev ev' H k f;
+ induction f as [| | | |? ? IHf1 ? IHf2|? ? IHf1 ? IHf2|? ? IHf
+ |? ? IHf1 ? ? IHf2|? ? IHf1 ? IHf2|];
+ simpl.
- reflexivity.
- reflexivity.
- reflexivity.
@@ -319,7 +322,7 @@ Lemma map_simpl : forall A B f l, @map A B f l = match l with
| a :: l=> (f a) :: (@map A B f l)
end.
Proof.
- destruct l ; reflexivity.
+ intros A B f l; destruct l ; reflexivity.
Qed.
@@ -469,7 +472,7 @@ Section S.
Lemma is_bool_inv : forall {TX : kind -> Type} {AF: Type} (k: kind) (f : TFormula TX AF k) res,
is_bool f = Some res -> f = if res then TT _ else FF _.
Proof.
- intros.
+ intros TX AF k f res H.
destruct f ; inversion H; reflexivity.
Qed.
@@ -689,7 +692,7 @@ Section S.
Definition is_X_inv : forall (k: kind) (f: TFormula TX AF k) x,
is_X f = Some x -> f = X k x.
Proof.
- destruct f ; simpl ; try congruence.
+ intros k f; destruct f ; simpl ; try congruence.
Qed.
Variable needA : Annot -> bool.
@@ -786,7 +789,7 @@ Section S.
Lemma if_same : forall {A: Type} (b: bool) (t:A),
(if b then t else t) = t.
Proof.
- destruct b ; reflexivity.
+ intros A b; destruct b ; reflexivity.
Qed.
Lemma is_cnf_tt_cnf_ff :
@@ -806,14 +809,14 @@ Section S.
is_cnf_tt f1 = true -> f1 = cnf_tt.
Proof.
unfold cnf_tt.
- destruct f1 ; simpl ; try congruence.
+ intros f1; destruct f1 ; simpl ; try congruence.
Qed.
Lemma is_cnf_ff_inv : forall f1,
is_cnf_ff f1 = true -> f1 = cnf_ff.
Proof.
unfold cnf_ff.
- destruct f1 ; simpl ; try congruence.
+ intros f1 ; destruct f1 as [|c f1] ; simpl ; try congruence.
destruct c ; simpl ; try congruence.
destruct f1 ; try congruence.
reflexivity.
@@ -822,7 +825,7 @@ Section S.
Lemma if_cnf_tt : forall f, (if is_cnf_tt f then cnf_tt else f) = f.
Proof.
- intros.
+ intros f.
destruct (is_cnf_tt f) eqn:EQ.
apply is_cnf_tt_inv in EQ;auto.
reflexivity.
@@ -831,7 +834,7 @@ Section S.
Lemma or_cnf_opt_cnf_ff : forall f,
or_cnf_opt cnf_ff f = f.
Proof.
- intros.
+ intros f.
unfold or_cnf_opt.
rewrite is_cnf_tt_cnf_ff.
simpl.
@@ -848,7 +851,7 @@ Section S.
and_cnf_opt (xcnf pol f1) (xcnf pol f2) =
xcnf pol (abs_and f1 f2 (if pol then AND else OR)).
Proof.
- unfold abs_and; intros.
+ unfold abs_and; intros k f1 f2 pol.
destruct (is_X f1) eqn:EQ1.
apply is_X_inv in EQ1.
subst.
@@ -868,7 +871,7 @@ Section S.
or_cnf_opt (xcnf pol f1) (xcnf pol f2) =
xcnf pol (abs_or f1 f2 (if pol then OR else AND)).
Proof.
- unfold abs_or; intros.
+ unfold abs_or; intros k f1 f2 pol.
destruct (is_X f1) eqn:EQ1.
apply is_X_inv in EQ1.
subst.
@@ -889,7 +892,7 @@ Section S.
Lemma xcnf_true_mk_arrow_l : forall b o t (f:TFormula TX AF b),
xcnf true (mk_arrow o (X b t) f) = xcnf true f.
Proof.
- destruct o ; simpl; auto.
+ intros b o; destruct o ; simpl; auto.
intros. rewrite or_cnf_opt_cnf_ff. reflexivity.
Qed.
@@ -907,8 +910,8 @@ Section S.
Lemma xcnf_true_mk_arrow_r : forall b o t (f:TFormula TX AF b),
xcnf true (mk_arrow o f (X b t)) = xcnf false f.
Proof.
- destruct o ; simpl; auto.
- - intros.
+ intros b o; destruct o ; simpl; auto.
+ - intros t f.
destruct (is_X f) eqn:EQ.
apply is_X_inv in EQ. subst. reflexivity.
simpl.
@@ -939,7 +942,7 @@ Section S.
Lemma and_cnf_opt_cnf_tt : forall f,
and_cnf_opt f cnf_tt = f.
Proof.
- intros.
+ intros f.
unfold and_cnf_opt.
simpl. rewrite orb_comm.
simpl.
@@ -951,7 +954,7 @@ Section S.
Lemma is_bool_abst_simpl : forall b (f:TFormula TX AF b),
is_bool (abst_simpl f) = is_bool f.
Proof.
- induction f ; simpl ; auto.
+ intros b f; induction f ; simpl ; auto.
rewrite needA_all.
reflexivity.
Qed.
@@ -959,7 +962,10 @@ Section S.
Lemma abst_simpl_correct : forall b (f:TFormula TX AF b) pol,
xcnf pol f = xcnf pol (abst_simpl f).
Proof.
- induction f; simpl;intros;
+ intros b f;
+ induction f as [| | | |? ? IHf1 f2 IHf2|? ? IHf1 f2 IHf2
+ |? ? IHf|? ? IHf1 ? f2 IHf2|? ? IHf1 f2 IHf2|f1 IHf1 f2 IHf2];
+ simpl;intros;
unfold mk_and,mk_or,mk_impl, mk_iff;
rewrite <- ?IHf;
try (rewrite <- !IHf1; rewrite <- !IHf2);
@@ -972,11 +978,11 @@ Section S.
destruct (is_bool f2); auto.
Qed.
- Ltac is_X :=
+ Ltac is_X t :=
match goal with
| |-context[is_X ?X] =>
let f := fresh "EQ" in
- destruct (is_X X) eqn:f ;
+ destruct (is_X X) as [t|] eqn:f ;
[apply is_X_inv in f|]
end.
@@ -995,10 +1001,10 @@ Section S.
Proof.
unfold or_is_X.
intros k f1 f2.
- repeat is_X.
- exists t ; intuition.
+ is_X t; is_X t0.
exists t ; intuition.
exists t ; intuition.
+ exists t0 ; intuition.
congruence.
Qed.
@@ -1008,8 +1014,8 @@ Section S.
| None => mk_iff xcnf pol f1 f2
end = mk_iff xcnf pol f1 f2.
Proof.
- intros.
- destruct (is_bool f2) eqn:EQ; auto.
+ intros k f1 f2 pol.
+ destruct (is_bool f2) as [b|] eqn:EQ; auto.
apply is_bool_inv in EQ.
subst.
unfold mk_iff.
@@ -1024,7 +1030,7 @@ Section S.
(pol : bool),
xcnf pol (IFF f1 f2) = xcnf pol (abst_iff abst_form pol f1 f2).
Proof.
- intros; simpl.
+ intros k f1 f2 IHf1 IHf2 pol; simpl.
assert (D1 :mk_iff xcnf pol f1 f2 = mk_iff xcnf pol (abst_simpl f1) (abst_simpl f2)).
{
simpl.
@@ -1066,7 +1072,7 @@ Section S.
(pol : bool),
xcnf pol (EQ f1 f2) = xcnf pol (abst_form pol (EQ f1 f2)).
Proof.
- intros.
+ intros f1 f2 IHf1 IHf2 pol.
change (xcnf pol (IFF f1 f2) = xcnf pol (abst_form pol (EQ f1 f2))).
rewrite abst_iff_correct by assumption.
simpl. unfold abst_iff, abst_eq.
@@ -1080,7 +1086,10 @@ Section S.
Lemma abst_form_correct : forall b (f:TFormula TX AF b) pol,
xcnf pol f = xcnf pol (abst_form pol f).
Proof.
- induction f;intros.
+ intros b f;
+ induction f as [| | | |? ? IHf1 ? IHf2|? ? IHf1 ? IHf2|? f IHf
+ |? f1 IHf1 o f2 IHf2|? IHf1 ? IHf2|];
+ intros pol.
- simpl. destruct pol ; reflexivity.
- simpl. destruct pol ; reflexivity.
- simpl. reflexivity.
@@ -1178,14 +1187,14 @@ Section S.
Lemma radd_term_term : forall a' a cl, radd_term a a' = inl cl -> add_term a a' = Some cl.
Proof.
- induction a' ; simpl.
- - intros.
- destruct (deduce (fst a) (fst a)).
+ intros a'; induction a' as [|a a' IHa']; simpl.
+ - intros a cl H.
+ destruct (deduce (fst a) (fst a)) as [t|].
destruct (unsat t). congruence.
inversion H. reflexivity.
inversion H ;reflexivity.
- - intros.
- destruct (deduce (fst a0) (fst a)).
+ - intros a0 cl H.
+ destruct (deduce (fst a0) (fst a)) as [t|].
destruct (unsat t). congruence.
destruct (radd_term a0 a') eqn:RADD; try congruence.
inversion H. subst.
@@ -1201,14 +1210,14 @@ Section S.
Lemma radd_term_term' : forall a' a cl, add_term a a' = Some cl -> radd_term a a' = inl cl.
Proof.
- induction a' ; simpl.
- - intros.
- destruct (deduce (fst a) (fst a)).
+ intros a'; induction a' as [|a a' IHa']; simpl.
+ - intros a cl H.
+ destruct (deduce (fst a) (fst a)) as [t|].
destruct (unsat t). congruence.
inversion H. reflexivity.
inversion H ;reflexivity.
- - intros.
- destruct (deduce (fst a0) (fst a)).
+ - intros a0 cl H.
+ destruct (deduce (fst a0) (fst a)) as [t|].
destruct (unsat t). congruence.
destruct (add_term a0 a') eqn:RADD; try congruence.
inversion H. subst.
@@ -1229,7 +1238,7 @@ Section S.
unfold xor_clause_cnf.
assert (ACC: fst (@nil clause,@nil Annot) = nil).
reflexivity.
- intros.
+ intros a f.
set (F1:= (fun '(acc, tg) (e : clause) =>
match ror_clause a e with
| inl cl => (cl :: acc, tg)
@@ -1243,15 +1252,15 @@ Section S.
revert ACC.
generalize (@nil clause,@nil Annot).
generalize (@nil clause).
- induction f ; simpl ; auto.
- intros.
+ induction f as [|a0 f IHf]; simpl ; auto.
+ intros ? p ?.
apply IHf.
unfold F1 , F2.
destruct p ; simpl in * ; subst.
clear.
revert a0.
- induction a; simpl; auto.
- intros.
+ induction a as [|a a0 IHa]; simpl; auto.
+ intros a1.
destruct (radd_term a a1) eqn:RADD.
apply radd_term_term in RADD.
rewrite RADD.
@@ -1266,14 +1275,14 @@ Section S.
fst (ror_clause_cnf a f) = or_clause_cnf a f.
Proof.
unfold ror_clause_cnf,or_clause_cnf.
- destruct a ; auto.
+ intros a; destruct a ; auto.
apply xror_clause_clause.
Qed.
Lemma ror_cnf_cnf : forall f1 f2, fst (ror_cnf f1 f2) = or_cnf f1 f2.
Proof.
- induction f1 ; simpl ; auto.
- intros.
+ intros f1; induction f1 as [|a f1 IHf1] ; simpl ; auto.
+ intros f2.
specialize (IHf1 f2).
destruct(ror_cnf f1 f2).
rewrite <- ror_clause_clause.
@@ -1286,7 +1295,7 @@ Section S.
Lemma ror_opt_cnf_cnf : forall f1 f2, fst (ror_cnf_opt f1 f2) = or_cnf_opt f1 f2.
Proof.
unfold ror_cnf_opt, or_cnf_opt.
- intros.
+ intros f1 f2.
destruct (is_cnf_tt f1).
- simpl ; auto.
- simpl. destruct (is_cnf_tt f2) ; simpl ; auto.
@@ -1299,7 +1308,7 @@ Section S.
fst (ratom f a) = f.
Proof.
unfold ratom.
- intros.
+ intros f a.
destruct (is_cnf_ff f || is_cnf_tt f); auto.
Qed.
@@ -1308,7 +1317,7 @@ Section S.
(IHf2 : forall pol : bool, fst (rxcnf pol f2) = xcnf pol f2),
forall pol : bool, fst (rxcnf_and rxcnf pol f1 f2) = mk_and xcnf pol f1 f2.
Proof.
- intros.
+ intros TX AF k f1 f2 IHf1 IHf2 pol.
unfold mk_and, rxcnf_and.
specialize (IHf1 pol).
specialize (IHf2 pol).
@@ -1327,7 +1336,7 @@ Section S.
(IHf2 : forall pol : bool, fst (rxcnf pol f2) = xcnf pol f2),
forall pol : bool, fst (rxcnf_or rxcnf pol f1 f2) = mk_or xcnf pol f1 f2.
Proof.
- intros.
+ intros TX AF k f1 f2 IHf1 IHf2 pol.
unfold rxcnf_or, mk_or.
specialize (IHf1 pol).
specialize (IHf2 pol).
@@ -1346,7 +1355,7 @@ Section S.
(IHf2 : forall pol : bool, fst (rxcnf pol f2) = xcnf pol f2),
forall pol : bool, fst (rxcnf_impl rxcnf pol f1 f2) = mk_impl xcnf pol f1 f2.
Proof.
- intros.
+ intros TX AF k f1 f2 IHf1 IHf2 pol.
unfold rxcnf_impl, mk_impl, mk_or.
specialize (IHf1 (negb pol)).
specialize (IHf2 pol).
@@ -1359,7 +1368,7 @@ Section S.
destruct pol;auto.
generalize (is_cnf_ff_inv (xcnf (negb true) f1)).
destruct (is_cnf_ff (xcnf (negb true) f1)).
- + intros.
+ + intros H.
rewrite H by auto.
unfold or_cnf_opt.
simpl.
@@ -1384,18 +1393,18 @@ Section S.
(IHf2 : forall pol : bool, fst (rxcnf pol f2) = xcnf pol f2),
forall pol : bool, fst (rxcnf_iff rxcnf pol f1 f2) = mk_iff xcnf pol f1 f2.
Proof.
- intros.
+ intros TX AF k f1 f2 IHf1 IHf2 pol.
unfold rxcnf_iff.
unfold mk_iff.
rewrite <- (IHf1 (negb pol)).
rewrite <- (IHf1 pol).
rewrite <- (IHf2 false).
rewrite <- (IHf2 true).
- destruct (rxcnf (negb pol) f1).
- destruct (rxcnf false f2).
- destruct (rxcnf pol f1).
- destruct (rxcnf true f2).
- destruct (ror_cnf_opt (and_cnf_opt c c0) (and_cnf_opt c1 c2)) eqn:EQ.
+ destruct (rxcnf (negb pol) f1) as [c ?].
+ destruct (rxcnf false f2) as [c0 ?].
+ destruct (rxcnf pol f1) as [c1 ?].
+ destruct (rxcnf true f2) as [c2 ?].
+ destruct (ror_cnf_opt (and_cnf_opt c c0) (and_cnf_opt c1 c2)) as [c3 l3] eqn:EQ.
simpl.
change c3 with (fst (c3,l3)).
rewrite <- EQ. rewrite ror_opt_cnf_cnf.
@@ -1405,7 +1414,7 @@ Section S.
Lemma rxcnf_xcnf : forall {TX : kind -> Type} {AF:Type} (k: kind) (f:TFormula TX AF k) pol,
fst (rxcnf pol f) = xcnf pol f.
Proof.
- induction f ; simpl ; auto.
+ intros TX AF k f; induction f ; simpl ; auto; intros pol.
- destruct pol; simpl ; auto.
- destruct pol; simpl ; auto.
- destruct pol ; simpl ; auto.
@@ -1463,7 +1472,7 @@ Section S.
Lemma eval_cnf_and_opt : forall env x y, eval_cnf env (and_cnf_opt x y) <-> eval_cnf env (and_cnf x y).
Proof.
unfold and_cnf_opt.
- intros.
+ intros env x y.
destruct (is_cnf_ff x) eqn:F1.
{ apply is_cnf_ff_inv in F1.
simpl. subst.
@@ -1501,14 +1510,14 @@ Section S.
Lemma add_term_correct : forall env t cl , eval_opt_clause env (add_term t cl) <-> eval_clause env (t::cl).
Proof.
- induction cl.
+ intros env t cl; induction cl as [|a cl IHcl].
- (* BC *)
simpl.
case_eq (deduce (fst t) (fst t)) ; try tauto.
- intros.
+ intros t0 H.
generalize (@deduce_prop _ _ _ H env).
case_eq (unsat t0) ; try tauto.
- { intros.
+ { intros H0 ?.
generalize (@unsat_prop _ H0 env).
unfold eval_clause.
rewrite make_conj_cons.
@@ -1518,9 +1527,9 @@ Section S.
- (* IC *)
simpl.
case_eq (deduce (fst t) (fst a));
- intros.
+ intros t0; [intros H|].
generalize (@deduce_prop _ _ _ H env).
- case_eq (unsat t0); intros.
+ case_eq (unsat t0); intros H0 H1.
{
generalize (@unsat_prop _ H0 env).
simpl.
@@ -1557,9 +1566,9 @@ Section S.
Lemma or_clause_correct : forall cl cl' env, eval_opt_clause env (or_clause cl cl') <-> eval_clause env cl \/ eval_clause env cl'.
Proof.
- induction cl.
+ intros cl; induction cl as [|a cl IHcl].
- simpl. unfold eval_clause at 2. simpl. tauto.
- - intros *.
+ - intros cl' env.
simpl.
assert (HH := add_term_correct env a cl').
assert (eval_tt env a \/ ~ eval_tt env a) by (apply no_middle_eval').
@@ -1579,17 +1588,17 @@ Section S.
Proof.
unfold eval_cnf.
unfold or_clause_cnf.
- intros until t.
+ intros env t.
set (F := (fun (acc : list clause) (e : clause) =>
match or_clause t e with
| Some cl => cl :: acc
| None => acc
end)).
intro f.
- assert ( make_conj (eval_clause env) (fold_left F f nil) <-> (eval_clause env t \/ make_conj (eval_clause env) f) /\ make_conj (eval_clause env) nil).
+ assert ( make_conj (eval_clause env) (fold_left F f nil) <-> (eval_clause env t \/ make_conj (eval_clause env) f) /\ make_conj (eval_clause env) nil) as H.
{
generalize (@nil clause) as acc.
- induction f.
+ induction f as [|a f IHf].
- simpl.
intros ; tauto.
- intros.
@@ -1634,7 +1643,7 @@ Section S.
Lemma or_cnf_correct : forall env f f', eval_cnf env (or_cnf f f') <-> (eval_cnf env f) \/ (eval_cnf env f').
Proof.
- induction f.
+ intros env f; induction f as [|a f IHf].
unfold eval_cnf.
simpl.
tauto.
@@ -1652,7 +1661,7 @@ Section S.
Lemma or_cnf_opt_correct : forall env f f', eval_cnf env (or_cnf_opt f f') <-> eval_cnf env (or_cnf f f').
Proof.
unfold or_cnf_opt.
- intros.
+ intros env f f'.
destruct (is_cnf_tt f) eqn:TF.
{ simpl.
apply is_cnf_tt_inv in TF.
@@ -1690,7 +1699,7 @@ Section S.
Lemma hold_eTT : forall k, hold k (eTT k).
Proof.
- destruct k ; simpl; auto.
+ intros k; destruct k ; simpl; auto.
Qed.
Hint Resolve hold_eTT : tauto.
@@ -1698,7 +1707,7 @@ Section S.
Lemma hold_eFF : forall k,
hold k (eNOT k (eFF k)).
Proof.
- destruct k ; simpl;auto.
+ intros k; destruct k ; simpl;auto.
Qed.
Hint Resolve hold_eFF : tauto.
@@ -1706,7 +1715,7 @@ Section S.
Lemma hold_eAND : forall k r1 r2,
hold k (eAND k r1 r2) <-> (hold k r1 /\ hold k r2).
Proof.
- destruct k ; simpl.
+ intros k; destruct k ; simpl.
- intros. apply iff_refl.
- apply andb_true_iff.
Qed.
@@ -1714,7 +1723,7 @@ Section S.
Lemma hold_eOR : forall k r1 r2,
hold k (eOR k r1 r2) <-> (hold k r1 \/ hold k r2).
Proof.
- destruct k ; simpl.
+ intros k; destruct k ; simpl.
- intros. apply iff_refl.
- apply orb_true_iff.
Qed.
@@ -1722,9 +1731,9 @@ Section S.
Lemma hold_eNOT : forall k e,
hold k (eNOT k e) <-> not (hold k e).
Proof.
- destruct k ; simpl.
+ intros k; destruct k ; simpl.
- intros. apply iff_refl.
- - intros. unfold is_true.
+ - intros e. unfold is_true.
rewrite negb_true_iff.
destruct e ; intuition congruence.
Qed.
@@ -1732,9 +1741,9 @@ Section S.
Lemma hold_eIMPL : forall k e1 e2,
hold k (eIMPL k e1 e2) <-> (hold k e1 -> hold k e2).
Proof.
- destruct k ; simpl.
+ intros k; destruct k ; simpl.
- intros. apply iff_refl.
- - intros.
+ - intros e1 e2.
unfold is_true.
destruct e1,e2 ; simpl ; intuition congruence.
Qed.
@@ -1742,9 +1751,9 @@ Section S.
Lemma hold_eIFF : forall k e1 e2,
hold k (eIFF k e1 e2) <-> (hold k e1 <-> hold k e2).
Proof.
- destruct k ; simpl.
+ intros k; destruct k ; simpl.
- intros. apply iff_refl.
- - intros.
+ - intros e1 e2.
unfold is_true.
rewrite eqb_true_iff.
destruct e1,e2 ; simpl ; intuition congruence.
@@ -1768,7 +1777,7 @@ Section S.
eval_cnf env (xcnf pol (IMPL f1 o f2)) ->
hold k (eval_f e_rtyp (eval env) (if pol then IMPL f1 o f2 else NOT (IMPL f1 o f2))).
Proof.
- simpl; intros. unfold mk_impl in H.
+ simpl; intros k f1 o f2 IHf1 IHf2 pol env H. unfold mk_impl in H.
destruct pol.
+ simpl.
rewrite hold_eIMPL.
@@ -1810,7 +1819,7 @@ Section S.
hold isBool (eIFF isBool e1 e2) <-> e1 = e2.
Proof.
simpl.
- destruct e1,e2 ; simpl ; intuition congruence.
+ intros e1 e2; destruct e1,e2 ; simpl ; intuition congruence.
Qed.
@@ -1828,7 +1837,7 @@ Section S.
hold k (eval_f e_rtyp (eval env) (if pol then IFF f1 f2 else NOT (IFF f1 f2))).
Proof.
simpl.
- intros.
+ intros k f1 f2 IHf1 IHf2 pol env H.
rewrite mk_iff_is_bool in H.
unfold mk_iff in H.
destruct pol;
@@ -1858,7 +1867,10 @@ Section S.
Lemma xcnf_correct : forall (k: kind) (f : @GFormula Term rtyp Annot unit k) pol env,
eval_cnf env (xcnf pol f) -> hold k (eval_f e_rtyp (eval env) (if pol then f else NOT f)).
Proof.
- induction f.
+ intros k f;
+ induction f as [| | | |? ? IHf1 ? IHf2|? ? IHf1 ? IHf2|? ? IHf
+ |? ? IHf1 ? ? IHf2|? ? IHf1 f2 IHf2|f1 IHf1 f2 IHf2];
+ intros pol env H.
- (* TT *)
unfold eval_cnf.
simpl.
@@ -1881,13 +1893,13 @@ Section S.
intros.
eapply negate_correct ; eauto.
- (* AND *)
- destruct pol ; simpl.
+ destruct pol ; simpl in H.
+ (* pol = true *)
intros.
rewrite eval_cnf_and_opt in H.
unfold and_cnf in H.
rewrite eval_cnf_app in H.
- destruct H.
+ destruct H as [H H0].
apply hold_eAND; split.
apply (IHf1 _ _ H).
apply (IHf2 _ _ H0).
@@ -1907,7 +1919,7 @@ Section S.
rewrite hold_eNOT.
tauto.
- (* OR *)
- simpl.
+ simpl in H.
destruct pol.
+ (* pol = true *)
intros. unfold mk_or in H.
@@ -1947,8 +1959,8 @@ Section S.
- (* IMPL *)
apply xcnf_impl; auto.
- apply xcnf_iff ; auto.
- - simpl.
- destruct (is_bool f2) eqn:EQ.
+ - simpl in H.
+ destruct (is_bool f2) as [b|] eqn:EQ.
+ apply is_bool_inv in EQ.
destruct b; subst; intros;
apply IHf1 in H;
@@ -1996,17 +2008,17 @@ Section S.
Lemma cnf_checker_sound : forall t w, cnf_checker t w = true -> forall env, eval_cnf env t.
Proof.
unfold eval_cnf.
- induction t.
+ intros t; induction t as [|a t IHt].
(* bc *)
simpl.
auto.
(* ic *)
simpl.
- destruct w.
+ intros w; destruct w as [|w ?].
intros ; discriminate.
- case_eq (checker a w) ; intros ; try discriminate.
+ case_eq (checker a w) ; intros H H0 env ** ; try discriminate.
generalize (@checker_sound _ _ H env).
- generalize (IHt _ H0 env) ; intros.
+ generalize (IHt _ H0 env) ; intros H1 H2.
destruct t.
red ; intro.
rewrite <- make_conj_impl in H2.
@@ -2021,7 +2033,7 @@ Section S.
Lemma tauto_checker_sound : forall t w, tauto_checker t w = true -> forall env, eval_f e_rtyp (eval env) t.
Proof.
unfold tauto_checker.
- intros.
+ intros t w H env.
change (eval_f e_rtyp (eval env) t) with (eval_f e_rtyp (eval env) (if true then t else TT isProp)).
apply (xcnf_correct t true).
eapply cnf_checker_sound ; eauto.
@@ -2032,7 +2044,10 @@ Section S.
Lemma eval_bf_map : forall T U (fct: T-> U) env (k: kind) (f:BFormula T k) ,
eval_bf env (map_bformula fct f) = eval_bf (fun b x => env b (fct x)) f.
Proof.
- induction f ; simpl ; try (rewrite IHf1 ; rewrite IHf2) ; auto.
+ intros T U fct env k f;
+ induction f as [| | | |? ? IHf1 ? IHf2|? ? IHf1 ? IHf2|? ? IHf
+ |? ? IHf1 ? ? IHf2|? ? IHf1 ? IHf2|? IHf1 ? IHf2];
+ simpl ; try (rewrite IHf1 ; rewrite IHf2) ; auto.
rewrite <- IHf. auto.
Qed.
diff --git a/theories/micromega/ZCoeff.v b/theories/micromega/ZCoeff.v
index 4e04adaddb..aaaeb9e118 100644
--- a/theories/micromega/ZCoeff.v
+++ b/theories/micromega/ZCoeff.v
@@ -121,7 +121,7 @@ Qed.
Lemma phi_pos1_pos : forall x : positive, 0 < phi_pos1 x.
Proof.
-induction x as [x IH | x IH |]; simpl;
+intros x; induction x as [x IH | x IH |]; simpl;
try apply (Rplus_pos_pos sor); try apply (Rtimes_pos_pos sor); try apply (Rplus_pos_pos sor);
try apply (Rlt_0_1 sor); assumption.
Qed.
diff --git a/theories/micromega/ZifyClasses.v b/theories/micromega/ZifyClasses.v
index 37eef12381..f6ade67c5f 100644
--- a/theories/micromega/ZifyClasses.v
+++ b/theories/micromega/ZifyClasses.v
@@ -210,7 +210,7 @@ Qed.
Lemma eq_iff : forall (P Q : Prop), P = Q -> (P <-> Q).
Proof.
- intros.
+ intros P Q H.
rewrite H.
apply iff_refl.
Defined.
diff --git a/theories/micromega/ZifyInst.v b/theories/micromega/ZifyInst.v
index 0e135ba793..9881e73f76 100644
--- a/theories/micromega/ZifyInst.v
+++ b/theories/micromega/ZifyInst.v
@@ -139,7 +139,7 @@ Add Zify BinRel Op_pos_le.
Lemma eq_pos_inj : forall (x y:positive), x = y <-> Z.pos x = Z.pos y.
Proof.
- intros.
+ intros x y.
apply (iff_sym (Pos2Z.inj_iff x y)).
Qed.
@@ -186,7 +186,7 @@ Add Zify UnOp Op_pos_pred.
Instance Op_pos_predN : UnOp Pos.pred_N :=
{ TUOp := fun x => x - 1 ;
- TUOpInj := ltac: (now destruct x; rewrite N.pos_pred_spec) }.
+ TUOpInj x := ltac: (now destruct x; rewrite N.pos_pred_spec) }.
Add Zify UnOp Op_pos_predN.
Instance Op_pos_of_succ_nat : UnOp Pos.of_succ_nat :=
@@ -195,7 +195,7 @@ Add Zify UnOp Op_pos_of_succ_nat.
Instance Op_pos_of_nat : UnOp Pos.of_nat :=
{ TUOp := fun x => Z.max 1 x ;
- TUOpInj := ltac: (now destruct x;
+ TUOpInj x := ltac: (now destruct x;
[|rewrite <- Pos.of_nat_succ, <- (Nat2Z.inj_max 1)]) }.
Add Zify UnOp Op_pos_of_nat.
@@ -445,7 +445,7 @@ Add Zify UnOp Op_Z_quot2.
Lemma of_nat_to_nat_eq : forall x, Z.of_nat (Z.to_nat x) = Z.max 0 x.
Proof.
- destruct x.
+ intros x; destruct x.
- reflexivity.
- rewrite Z2Nat.id.
reflexivity.
diff --git a/theories/micromega/Ztac.v b/theories/micromega/Ztac.v
index 5fb92aba44..a97ea85ceb 100644
--- a/theories/micromega/Ztac.v
+++ b/theories/micromega/Ztac.v
@@ -26,7 +26,7 @@ Qed.
Lemma elim_concl_eq :
forall x y, (x < y \/ y < x -> False) -> x = y.
Proof.
- intros.
+ intros x y H.
destruct (Z_lt_le_dec x y).
exfalso. apply H ; auto.
destruct (Zle_lt_or_eq y x);auto.
@@ -37,7 +37,7 @@ Qed.
Lemma elim_concl_le :
forall x y, (y < x -> False) -> x <= y.
Proof.
- intros.
+ intros x y H.
destruct (Z_lt_le_dec y x).
exfalso ; auto.
auto.
@@ -46,7 +46,7 @@ Qed.
Lemma elim_concl_lt :
forall x y, (y <= x -> False) -> x < y.
Proof.
- intros.
+ intros x y H.
destruct (Z_lt_le_dec x y).
auto.
exfalso ; auto.
@@ -93,7 +93,7 @@ Qed.
Lemma mul_le : forall e1 e2, 0 <= e1 -> 0 <= e2 -> 0 <= e1*e2.
Proof.
- intros.
+ intros e1 e2 H H0.
change 0 with (0* e2).
apply Zmult_le_compat_r; auto.
Qed.
diff --git a/theories/setoid_ring/InitialRing.v b/theories/setoid_ring/InitialRing.v
index bb98a447dc..c33beaf8cd 100644
--- a/theories/setoid_ring/InitialRing.v
+++ b/theories/setoid_ring/InitialRing.v
@@ -104,7 +104,7 @@ Section ZMORPHISM.
Lemma get_signZ_th : sign_theory Z.opp Zeq_bool get_signZ.
Proof.
constructor.
- destruct c;intros;try discriminate.
+ intros c;destruct c;intros ? H;try discriminate.
injection H as [= <-].
simpl. unfold Zeq_bool. rewrite Z.compare_refl. trivial.
Qed.
@@ -119,7 +119,7 @@ Section ZMORPHISM.
Lemma same_gen : forall x, gen_phiPOS1 x == gen_phiPOS x.
Proof.
- induction x;simpl.
+ intros x;induction x as [x IHx|x IHx|];simpl.
rewrite IHx;destruct x;simpl;norm.
rewrite IHx;destruct x;simpl;norm.
rrefl.
@@ -128,7 +128,7 @@ Section ZMORPHISM.
Lemma ARgen_phiPOS_Psucc : forall x,
gen_phiPOS1 (Pos.succ x) == 1 + (gen_phiPOS1 x).
Proof.
- induction x;simpl;norm.
+ intros x;induction x as [x IHx|x IHx|];simpl;norm.
rewrite IHx;norm.
add_push 1;rrefl.
Qed.
@@ -136,7 +136,8 @@ Section ZMORPHISM.
Lemma ARgen_phiPOS_add : forall x y,
gen_phiPOS1 (x + y) == (gen_phiPOS1 x) + (gen_phiPOS1 y).
Proof.
- induction x;destruct y;simpl;norm.
+ intros x;induction x as [x IHx|x IHx|];
+ intros y;destruct y as [y|y|];simpl;norm.
rewrite Pos.add_carry_spec.
rewrite ARgen_phiPOS_Psucc.
rewrite IHx;norm.
@@ -152,7 +153,7 @@ Section ZMORPHISM.
Lemma ARgen_phiPOS_mult :
forall x y, gen_phiPOS1 (x * y) == gen_phiPOS1 x * gen_phiPOS1 y.
Proof.
- induction x;intros;simpl;norm.
+ intros x;induction x as [x IHx|x IHx|];intros;simpl;norm.
rewrite ARgen_phiPOS_add;simpl;rewrite IHx;norm.
rewrite IHx;rrefl.
Qed.
@@ -169,7 +170,7 @@ Section ZMORPHISM.
(*morphisms are extensionally equal*)
Lemma same_genZ : forall x, [x] == gen_phiZ1 x.
Proof.
- destruct x;simpl; try rewrite (same_gen ARth);rrefl.
+ intros x;destruct x;simpl; try rewrite (same_gen ARth);rrefl.
Qed.
Lemma gen_Zeqb_ok : forall x y,
@@ -198,7 +199,7 @@ Section ZMORPHISM.
Lemma gen_phiZ_add : forall x y, [x + y] == [x] + [y].
Proof.
intros x y; repeat rewrite same_genZ; generalize x y;clear x y.
- destruct x, y; simpl; norm.
+ intros x y;destruct x, y; simpl; norm.
apply (ARgen_phiPOS_add ARth).
apply gen_phiZ1_pos_sub.
rewrite gen_phiZ1_pos_sub. apply (Radd_comm Rth).
@@ -301,7 +302,7 @@ Section NMORPHISM.
Lemma same_genN : forall x, [x] == gen_phiN1 x.
Proof.
- destruct x;simpl. reflexivity.
+ intros x;destruct x;simpl. reflexivity.
now rewrite (same_gen Rsth Reqe ARth).
Qed.
@@ -421,7 +422,7 @@ Section NWORDMORPHISM.
Lemma gen_phiNword0_ok : forall w, Nw_is0 w = true -> gen_phiNword w == 0.
Proof.
-induction w; simpl; intros; auto.
+intros w; induction w as [|a w IHw]; simpl; intros; auto.
reflexivity.
destruct a.
@@ -436,17 +437,17 @@ Qed.
Lemma gen_phiNword_cons : forall w n,
gen_phiNword (n::w) == gen_phiN rO rI radd rmul n - gen_phiNword w.
-induction w.
- destruct n; simpl; norm.
+intros w; induction w.
+ intros n; destruct n; simpl; norm.
- intros.
+ intros n.
destruct n; norm.
Qed.
Lemma gen_phiNword_Nwcons : forall w n,
gen_phiNword (Nwcons n w) == gen_phiN rO rI radd rmul n - gen_phiNword w.
-destruct w; intros.
- destruct n; norm.
+intros w; destruct w; intros n0.
+ destruct n0; norm.
unfold Nwcons.
rewrite gen_phiNword_cons.
@@ -455,13 +456,13 @@ Qed.
Lemma gen_phiNword_ok : forall w1 w2,
Nweq_bool w1 w2 = true -> gen_phiNword w1 == gen_phiNword w2.
-induction w1; intros.
+intros w1; induction w1 as [|a w1 IHw1]; intros w2 H.
simpl.
rewrite (gen_phiNword0_ok _ H).
reflexivity.
rewrite gen_phiNword_cons.
- destruct w2.
+ destruct w2 as [|n w2].
simpl in H.
destruct a; try discriminate.
rewrite (gen_phiNword0_ok _ H).
@@ -481,7 +482,7 @@ Qed.
Lemma Nwadd_ok : forall x y,
gen_phiNword (Nwadd x y) == gen_phiNword x + gen_phiNword y.
-induction x; intros.
+intros x; induction x as [|n x IHx]; intros y.
simpl.
norm.
@@ -507,7 +508,7 @@ Qed.
Lemma Nwscal_ok : forall n x,
gen_phiNword (Nwscal n x) == gen_phiN rO rI radd rmul n * gen_phiNword x.
-induction x; intros.
+intros n x; induction x as [|a x IHx]; intros.
norm.
simpl Nwscal.
@@ -521,7 +522,7 @@ Qed.
Lemma Nwmul_ok : forall x y,
gen_phiNword (Nwmul x y) == gen_phiNword x * gen_phiNword y.
-induction x; intros.
+intros x; induction x as [|a x IHx]; intros.
norm.
destruct a.
@@ -626,7 +627,7 @@ Qed.
Lemma Ztriv_div_th : div_theory req Z.add Z.mul zphi Z.quotrem.
Proof.
constructor.
- intros; generalize (Z.quotrem_eq a b); case Z.quotrem; intros; subst.
+ intros a b; generalize (Z.quotrem_eq a b); case Z.quotrem; intros; subst.
rewrite Z.mul_comm; rsimpl.
Qed.
@@ -634,7 +635,7 @@ Qed.
Lemma Ntriv_div_th : div_theory req N.add N.mul nphi N.div_eucl.
constructor.
- intros; generalize (N.div_eucl_spec a b); case N.div_eucl; intros; subst.
+ intros a b; generalize (N.div_eucl_spec a b); case N.div_eucl; intros; subst.
rewrite N.mul_comm; rsimpl.
Qed.
diff --git a/theories/setoid_ring/Ring.v b/theories/setoid_ring/Ring.v
index a66037a956..25b79d1fb2 100644
--- a/theories/setoid_ring/Ring.v
+++ b/theories/setoid_ring/Ring.v
@@ -17,22 +17,22 @@ Require Export Ring_tac.
Lemma BoolTheory :
ring_theory false true xorb andb xorb (fun b:bool => b) (eq(A:=bool)).
split; simpl.
-destruct x; reflexivity.
-destruct x; destruct y; reflexivity.
-destruct x; destruct y; destruct z; reflexivity.
+intros x; destruct x; reflexivity.
+intros x y; destruct x; destruct y; reflexivity.
+intros x y z; destruct x; destruct y; destruct z; reflexivity.
reflexivity.
-destruct x; destruct y; reflexivity.
-destruct x; destruct y; reflexivity.
-destruct x; destruct y; destruct z; reflexivity.
+intros x y; destruct x; destruct y; reflexivity.
+intros x y; destruct x; destruct y; reflexivity.
+intros x y z; destruct x; destruct y; destruct z; reflexivity.
reflexivity.
-destruct x; reflexivity.
+intros x; destruct x; reflexivity.
Qed.
Definition bool_eq (b1 b2:bool) :=
if b1 then b2 else negb b2.
Lemma bool_eq_ok : forall b1 b2, bool_eq b1 b2 = true -> b1 = b2.
-destruct b1; destruct b2; auto.
+intros b1 b2; destruct b1; destruct b2; auto.
Qed.
Ltac bool_cst t :=
diff --git a/theories/setoid_ring/Ring_polynom.v b/theories/setoid_ring/Ring_polynom.v
index a13b1fc738..0efd82c9bd 100644
--- a/theories/setoid_ring/Ring_polynom.v
+++ b/theories/setoid_ring/Ring_polynom.v
@@ -559,7 +559,9 @@ Section MakeRingPol.
Lemma Peq_ok P P' : (P ?== P') = true -> P === P'.
Proof.
unfold Pequiv.
- revert P';induction P;destruct P';simpl; intros H l; try easy.
+ revert P';induction P as [|p P IHP|P2 IHP1 p P3 IHP2];
+ intros P';destruct P' as [|p0 P'|P'1 p0 P'2];simpl;
+ intros H l; try easy.
- now apply (morph_eq CRmorph).
- destruct (Pos.compare_spec p p0); [ subst | easy | easy ].
now rewrite IHP.
@@ -643,13 +645,13 @@ Section MakeRingPol.
Lemma PaddC_ok c P l : (PaddC P c)@l == P@l + [c].
Proof.
- revert l;induction P;simpl;intros;Esimpl;trivial.
+ revert l;induction P as [| |P2 IHP1 p P3 IHP2];simpl;intros;Esimpl;trivial.
rewrite IHP2;rsimpl.
Qed.
Lemma PsubC_ok c P l : (PsubC P c)@l == P@l - [c].
Proof.
- revert l;induction P;simpl;intros.
+ revert l;induction P as [|p P IHP|P2 IHP1 p P3 IHP2];simpl;intros.
- Esimpl.
- rewrite IHP;rsimpl.
- rewrite IHP2;rsimpl.
@@ -657,7 +659,7 @@ Section MakeRingPol.
Lemma PmulC_aux_ok c P l : (PmulC_aux P c)@l == P@l * [c].
Proof.
- revert l;induction P;simpl;intros;Esimpl;trivial.
+ revert l;induction P as [| |P2 IHP1 p P3 IHP2];simpl;intros;Esimpl;trivial.
rewrite IHP1, IHP2;rsimpl. add_permut. mul_permut.
Qed.
@@ -673,7 +675,7 @@ Section MakeRingPol.
Lemma Popp_ok P l : (--P)@l == - P@l.
Proof.
- revert l;induction P;simpl;intros.
+ revert l;induction P as [|p P IHP|P2 IHP1 p P3 IHP2];simpl;intros.
- Esimpl.
- apply IHP.
- rewrite IHP1, IHP2;rsimpl.
@@ -686,7 +688,7 @@ Section MakeRingPol.
(PaddX Padd P' k P) @ l == P@l + P'@l * (hd l)^k.
Proof.
intros IHP'.
- revert k l. induction P;simpl;intros.
+ revert k l. induction P as [|p P IHP|P2 IHP1 p P3 IHP2];simpl;intros.
- add_permut.
- destruct p; simpl;
rewrite ?jump_pred_double; add_permut.
@@ -698,8 +700,9 @@ Section MakeRingPol.
Lemma Padd_ok P' P l : (P ++ P')@l == P@l + P'@l.
Proof.
- revert P l; induction P';simpl;intros;Esimpl.
- - revert p l; induction P;simpl;intros.
+ revert P l; induction P' as [|p P' IHP'|P'1 IHP'1 p P'2 IHP'2];
+ simpl;intros P l;Esimpl.
+ - revert p l; induction P as [|p P IHP|P2 IHP1 p P3 IHP2];simpl;intros p0 l.
+ Esimpl; add_permut.
+ destr_pos_sub; intros ->;Esimpl.
* now rewrite IHP'.
@@ -709,7 +712,7 @@ Section MakeRingPol.
* rewrite IHP2;simpl. rsimpl.
* rewrite IHP2;simpl. rewrite jump_pred_double. rsimpl.
* rewrite IHP'. rsimpl.
- - destruct P;simpl.
+ - destruct P as [|p0 ?|? ? ?];simpl.
+ Esimpl. add_permut.
+ destruct p0;simpl;Esimpl; rewrite IHP'2; simpl.
* rsimpl. add_permut.
@@ -725,14 +728,15 @@ Section MakeRingPol.
Lemma Psub_opp P' P : P -- P' === P ++ (--P').
Proof.
- revert P; induction P'; simpl; intros.
+ revert P; induction P' as [|p P' IHP'|P'1 IHP'1 p P'2 IHP'2]; simpl; intros P.
- intro l; Esimpl.
- - revert p; induction P; simpl; intros; try reflexivity.
+ - revert p; induction P; simpl; intros p0; try reflexivity.
+ destr_pos_sub; intros ->; now apply mkPinj_ext.
+ destruct p0; now apply PX_ext.
- - destruct P; simpl; try reflexivity.
+ - destruct P as [|p0 P|P2 p0 P3]; simpl; try reflexivity.
+ destruct p0; now apply PX_ext.
+ destr_pos_sub; intros ->; apply mkPX_ext; auto.
+ let p1 := match goal with |- PsubX _ _ ?p1 _ === _ => p1 end in
revert p1. induction P2; simpl; intros; try reflexivity.
destr_pos_sub; intros ->; now apply mkPX_ext.
Qed.
@@ -746,8 +750,8 @@ Section MakeRingPol.
(forall P l, (Pmul P P') @ l == P @ l * P' @ l) ->
forall P p l, (PmulI Pmul P' p P) @ l == P @ l * P' @ (jump p l).
Proof.
- intros IHP'.
- induction P;simpl;intros.
+ intros IHP' P.
+ induction P as [|p P IHP|? IHP1 ? ? IHP2];simpl;intros p0 l.
- Esimpl; mul_permut.
- destr_pos_sub; intros ->;Esimpl.
+ now rewrite IHP'.
@@ -761,10 +765,10 @@ Section MakeRingPol.
Lemma Pmul_ok P P' l : (P**P')@l == P@l * P'@l.
Proof.
- revert P l;induction P';simpl;intros.
+ revert P l;induction P' as [| |? IHP'1 ? ? IHP'2];simpl;intros P l.
- apply PmulC_ok.
- apply PmulI_ok;trivial.
- - destruct P.
+ - destruct P as [|p0|].
+ rewrite (ARmul_comm ARth). Esimpl.
+ Esimpl. f_equiv. rewrite IHP'1; Esimpl.
destruct p0;rewrite IHP'2;Esimpl.
@@ -821,7 +825,8 @@ Section MakeRingPol.
P@l == Q@l + [c] * M@@l * R@l.
Proof.
destruct cM as (c,M). revert M l.
- induction P; destruct M; intros l; simpl; auto;
+ induction P as [c0|p P ?|P2 ? ? P3 ?]; intros M; destruct M; intros l;
+ simpl; auto;
try (case ceqb_spec; intro He);
try (case Pos.compare_spec; intros He);
rewrite ?He;
@@ -858,7 +863,7 @@ Section MakeRingPol.
[fst cM1] * (snd cM1)@@l == P2@l ->
P1@l == (PNSubst1 P1 cM1 P2 n)@l.
Proof.
- revert P1. induction n; simpl; intros P1;
+ revert P1. induction n as [|n IHn]; simpl; intros P1;
generalize (POneSubst_ok P1 cM1 P2); destruct POneSubst;
intros; rewrite <- ?IHn; auto; reflexivity.
Qed.
@@ -890,7 +895,7 @@ Section MakeRingPol.
Lemma PSubstL_ok n LM1 P1 P2 l :
PSubstL P1 LM1 n = Some P2 -> MPcond LM1 l -> P1@l == P2@l.
Proof.
- revert P1. induction LM1 as [|(M2,P2') LM2 IH]; simpl; intros.
+ revert P1. induction LM1 as [|(M2,P2') LM2 IH]; simpl; intros P3 H **.
- discriminate.
- assert (H':=PNSubst_ok n P3 M2 P2'). destruct PNSubst.
* injection H as [= <-]. rewrite <- PSubstL1_ok; intuition.
@@ -900,7 +905,7 @@ Section MakeRingPol.
Lemma PNSubstL_ok m n LM1 P1 l :
MPcond LM1 l -> P1@l == (PNSubstL P1 LM1 m n)@l.
Proof.
- revert LM1 P1. induction m; simpl; intros;
+ revert LM1 P1. induction m as [|m IHm]; simpl; intros LM1 P2 H;
assert (H' := PSubstL_ok n LM1 P2); destruct PSubstL;
auto; try reflexivity.
rewrite <- IHm; auto.
@@ -979,7 +984,8 @@ Section POWER.
forall res P p, (Ppow_pos res P p)@l == res@l * (pow_pos Pmul P p)@l.
Proof.
intros subst_l_ok res P p. revert res.
- induction p;simpl;intros; rewrite ?subst_l_ok, ?Pmul_ok, ?IHp;
+ induction p as [p IHp|p IHp|];simpl;intros;
+ rewrite ?subst_l_ok, ?Pmul_ok, ?IHp;
mul_permut.
Qed.
@@ -987,7 +993,7 @@ Section POWER.
(forall P, subst_l P@l == P@l) ->
forall P n, (Ppow_N P n)@l == (pow_N P1 Pmul P n)@l.
Proof.
- destruct n;simpl.
+ intros ? P n; destruct n;simpl.
- reflexivity.
- rewrite Ppow_pos_ok by trivial. Esimpl.
Qed.
@@ -1057,8 +1063,9 @@ Section POWER.
PEeval l pe == (norm_aux pe)@l.
Proof.
intros.
- induction pe; cbn.
- - now rewrite (morph0 CRmorph).
+ induction pe as [| |c|p|pe1 IHpe1 pe2 IHpe2|? IHpe1 ? IHpe2|? IHpe1 ? IHpe2
+ |? IHpe|? IHpe n0]; cbn.
+ - now rewrite (morph0 CRmorph).
- now rewrite (morph1 CRmorph).
- reflexivity.
- apply mkX_ok.
@@ -1071,8 +1078,9 @@ Section POWER.
- rewrite IHpe1, IHpe2. now rewrite Pmul_ok.
- rewrite IHpe. Esimpl.
- rewrite Ppow_N_ok by reflexivity.
- rewrite (rpow_pow_N pow_th). destruct n0; simpl; Esimpl.
- induction p;simpl; now rewrite ?IHp, ?IHpe, ?Pms_ok, ?Pmul_ok.
+ rewrite (rpow_pow_N pow_th). destruct n0 as [|p]; simpl; Esimpl.
+ induction p as [p IHp|p IHp|];simpl;
+ now rewrite ?IHp, ?IHpe, ?Pms_ok, ?Pmul_ok.
Qed.
Lemma norm_subst_spec :
@@ -1125,7 +1133,7 @@ Section POWER.
Lemma mon_of_pol_ok : forall P m, mon_of_pol P = Some m ->
forall l, [fst m] * Mphi l (snd m) == P@l.
Proof.
- induction P;simpl;intros;Esimpl.
+ intros P; induction P as [c|p P IHP|P2 IHP1 ? P3 ?];simpl;intros m H l;Esimpl.
assert (H1 := (morph_eq CRmorph) c cO).
destruct (c ?=! cO).
discriminate.
@@ -1142,7 +1150,7 @@ Section POWER.
end with (P3 ?== P0).
assert (H := Peq_ok P3 P0).
destruct (P3 ?== P0).
- case_eq (mon_of_pol P2);try intros (cc, pp); intros.
+ case_eq (mon_of_pol P2);try intros (cc, pp); intros H0 H1.
inversion H1.
simpl.
rewrite mkVmon_ok;simpl.
@@ -1155,16 +1163,16 @@ Section POWER.
Lemma interp_PElist_ok : forall l lpe,
interp_PElist l lpe -> MPcond (mk_monpol_list lpe) l.
Proof.
- induction lpe;simpl. trivial.
- destruct a;simpl;intros.
+ intros l lpe; induction lpe as [|a lpe IHlpe];simpl. trivial.
+ destruct a as [p p0];simpl;intros H.
assert (HH:=mon_of_pol_ok (norm_subst 0 nil p));
destruct (mon_of_pol (norm_subst 0 nil p)).
split.
rewrite <- norm_subst_spec by exact I.
- destruct lpe;try destruct H;rewrite <- H;
+ destruct lpe;try destruct H as [H H0];rewrite <- H;
rewrite (norm_subst_spec 0 nil); try exact I;apply HH;trivial.
- apply IHlpe. destruct lpe;simpl;trivial. destruct H. exact H0.
- apply IHlpe. destruct lpe;simpl;trivial. destruct H. exact H0.
+ apply IHlpe. destruct lpe;simpl;trivial. destruct H as [H H0]. exact H0.
+ apply IHlpe. destruct lpe;simpl;trivial. destruct H as [H H0]. exact H0.
Qed.
Lemma norm_subst_ok : forall n l lpe pe,
@@ -1180,7 +1188,7 @@ Section POWER.
norm_subst n lmp pe1 ?== norm_subst n lmp pe2) = true ->
PEeval l pe1 == PEeval l pe2.
Proof.
- simpl;intros.
+ simpl;intros n l lpe pe1 pe2 **.
do 2 (rewrite (norm_subst_ok n l lpe);trivial).
apply Peq_ok;trivial.
Qed.
@@ -1285,36 +1293,36 @@ Section POWER.
Lemma mkmult_rec_ok : forall lm r, mkmult_rec r lm == r * r_list_pow lm.
Proof.
- induction lm;intros;simpl;Esimpl.
+ intros lm; induction lm as [|a lm IHlm];intros;simpl;Esimpl.
destruct a as (x,p);Esimpl.
rewrite IHlm. rewrite mkmult_pow_spec. Esimpl.
Qed.
Lemma mkmult1_ok : forall lm, mkmult1 lm == r_list_pow lm.
Proof.
- destruct lm;simpl;Esimpl.
+ intros lm; destruct lm as [|p lm];simpl;Esimpl.
destruct p. rewrite mkmult_rec_ok;rewrite mkpow_spec;Esimpl.
Qed.
Lemma mkmultm1_ok : forall lm, mkmultm1 lm == - r_list_pow lm.
Proof.
- destruct lm;simpl;Esimpl.
+ intros lm; destruct lm as [|p lm];simpl;Esimpl.
destruct p;rewrite mkmult_rec_ok. rewrite mkopp_pow_spec;Esimpl.
Qed.
Lemma r_list_pow_rev : forall l, r_list_pow (rev' l) == r_list_pow l.
Proof.
assert
- (forall l lr : list (R * positive), r_list_pow (rev_append l lr) == r_list_pow lr * r_list_pow l).
- induction l;intros;simpl;Esimpl.
- destruct a;rewrite IHl;Esimpl.
+ (forall l lr : list (R * positive), r_list_pow (rev_append l lr) == r_list_pow lr * r_list_pow l) as H.
+ intros l; induction l as [|a l IHl];intros;simpl;Esimpl.
+ destruct a as [r p];rewrite IHl;Esimpl.
rewrite (ARmul_comm ARth (pow_pos rmul r p)). reflexivity.
intros;unfold rev'. rewrite H;simpl;Esimpl.
Qed.
Lemma mkmult_c_pos_ok : forall c lm, mkmult_c_pos c lm == [c]* r_list_pow lm.
Proof.
- intros;unfold mkmult_c_pos;simpl.
+ intros c lm;unfold mkmult_c_pos;simpl.
assert (H := (morph_eq CRmorph) c cI).
rewrite <- r_list_pow_rev; destruct (c ?=! cI).
rewrite H;trivial;Esimpl.
@@ -1323,8 +1331,8 @@ Section POWER.
Lemma mkmult_c_ok : forall c lm, mkmult_c c lm == [c] * r_list_pow lm.
Proof.
- intros;unfold mkmult_c;simpl.
- case_eq (get_sign c);intros.
+ intros c lm;unfold mkmult_c;simpl.
+ case_eq (get_sign c);intros c0; try intros H.
assert (H1 := (morph_eq CRmorph) c0 cI).
destruct (c0 ?=! cI).
rewrite (morph_eq CRmorph _ _ (sign_spec get_sign_spec _ H)). Esimpl. rewrite H1;trivial.
@@ -1336,8 +1344,8 @@ Qed.
Lemma mkadd_mult_ok : forall rP c lm, mkadd_mult rP c lm == rP + [c]*r_list_pow lm.
Proof.
- intros;unfold mkadd_mult.
- case_eq (get_sign c);intros.
+ intros rP c lm;unfold mkadd_mult.
+ case_eq (get_sign c);intros c0; try intros H.
rewrite (morph_eq CRmorph _ _ (sign_spec get_sign_spec _ H));Esimpl.
rewrite mkmult_c_pos_ok;Esimpl.
rewrite mkmult_c_pos_ok;Esimpl.
@@ -1346,13 +1354,13 @@ Qed.
Lemma add_pow_list_ok :
forall r n l, r_list_pow (add_pow_list r n l) == pow_N rI rmul r n * r_list_pow l.
Proof.
- destruct n;simpl;intros;Esimpl.
+ intros r n; destruct n;simpl;intros;Esimpl.
Qed.
Lemma add_mult_dev_ok : forall P rP fv n lm,
add_mult_dev rP P fv n lm == rP + P@fv*pow_N rI rmul (hd fv) n * r_list_pow lm.
Proof.
- induction P;simpl;intros.
+ intros P; induction P as [|p P IHP|P2 IHP1 p P3 IHP2];simpl;intros rP fv n lm.
rewrite mkadd_mult_ok. rewrite add_pow_list_ok; Esimpl.
rewrite IHP. simpl. rewrite add_pow_list_ok; Esimpl.
change (match P3 with
@@ -1377,7 +1385,7 @@ Qed.
Lemma mult_dev_ok : forall P fv n lm,
mult_dev P fv n lm == P@fv * pow_N rI rmul (hd fv) n * r_list_pow lm.
Proof.
- induction P;simpl;intros;Esimpl.
+ intros P; induction P as [|p P IHP|P2 IHP1 p P3 IHP2];simpl;intros fv n lm;Esimpl.
rewrite mkmult_c_ok;rewrite add_pow_list_ok;Esimpl.
rewrite IHP. simpl;rewrite add_pow_list_ok;Esimpl.
change (match P3 with
@@ -1463,7 +1471,7 @@ Qed.
Lemma mkmult_pow_ok p r x : mkmult_pow r x p == r * x^p.
Proof.
- revert r; induction p;intros;simpl;Esimpl;rewrite !IHp;Esimpl.
+ revert r; induction p as [p IHp|p IHp|];intros;simpl;Esimpl;rewrite !IHp;Esimpl.
Qed.
Lemma mkpow_ok p x : mkpow x p == x^p.
diff --git a/theories/ssr/ssreflect.v b/theories/ssr/ssreflect.v
index 97a283b875..175cae8415 100644
--- a/theories/ssr/ssreflect.v
+++ b/theories/ssr/ssreflect.v
@@ -59,6 +59,15 @@ Declare ML Module "ssreflect_plugin".
Canonical foo_unlockable := #[#unlockable fun foo#]#.
This minimizes the comparison overhead for foo, while still allowing
rewrite unlock to expose big_foo_expression.
+
+ Additionally we provide default intro pattern ltac views:
+ - top of the stack actions:
+ => /[apply] := => hyp {}/hyp
+ => /[swap] := => x y; move: y x
+ (also swap and perserves let bindings)
+ => /[dup] := => x; have copy := x; move: copy x
+ (also copies and preserves let bindings)
+
More information about these definitions and their use can be found in the
ssreflect manual, and in specific comments below. **)
@@ -654,3 +663,50 @@ End Exports.
End NonPropType.
Export NonPropType.Exports.
+
+Module Export ipat.
+
+Notation "'[' 'apply' ']'" := (ltac:(let f := fresh "_top_" in move=> f {}/f))
+ (at level 0, only parsing) : ssripat_scope.
+
+(** We try to preserve the naming by matching the names from the goal.
+ We do 'move' to perform a hnf before trying to match. **)
+Notation "'[' 'swap' ']'" := (ltac:(move;
+ lazymatch goal with
+ | |- forall (x : _), _ => let x := fresh x in move=> x; move;
+ lazymatch goal with
+ | |- forall (y : _), _ => let y := fresh y in move=> y; move: y x
+ | |- let y := _ in _ => let y := fresh y in move=> y; move: @y x
+ | _ => let y := fresh "_top_" in move=> y; move: y x
+ end
+ | |- let x := _ in _ => let x := fresh x in move => x; move;
+ lazymatch goal with
+ | |- forall (y : _), _ => let y := fresh y in move=> y; move: y @x
+ | |- let y := _ in _ => let y := fresh y in move=> y; move: @y @x
+ | _ => let y := fresh "_top_" in move=> y; move: y x
+ end
+ | _ => let x := fresh "_top_" in let x := fresh x in move=> x; move;
+ lazymatch goal with
+ | |- forall (y : _), _ => let y := fresh y in move=> y; move: y @x
+ | |- let y := _ in _ => let y := fresh y in move=> y; move: @y @x
+ | _ => let y := fresh "_top_" in move=> y; move: y x
+ end
+ end))
+ (at level 0, only parsing) : ssripat_scope.
+
+Notation "'[' 'dup' ']'" := (ltac:(move;
+ lazymatch goal with
+ | |- forall (x : _), _ =>
+ let x := fresh x in move=> x;
+ let copy := fresh x in have copy := x; move: copy x
+ | |- let x := _ in _ =>
+ let x := fresh x in move=> x;
+ let copy := fresh x in pose copy := x;
+ do [unfold x in (value of copy)]; move: @copy @x
+ | |- _ =>
+ let x := fresh "_top_" in move=> x;
+ let copy := fresh "_top" in have copy := x; move: copy x
+ end))
+ (at level 0, only parsing) : ssripat_scope.
+
+End ipat.
diff --git a/theories/ssrmatching/ssrmatching.v b/theories/ssrmatching/ssrmatching.v
index feca62651d..fda6b860e6 100644
--- a/theories/ssrmatching/ssrmatching.v
+++ b/theories/ssrmatching/ssrmatching.v
@@ -25,7 +25,7 @@ Declare Scope ssrpatternscope.
Delimit Scope ssrpatternscope with pattern.
(* Notation to define shortcuts for the "X in t" part of a pattern. *)
-Notation "( X 'in' t )" := (_ : fun X => t) : ssrpatternscope.
+Notation "( X 'in' t )" := (_ : fun X => t) (only parsing) : ssrpatternscope.
(* Some shortcuts for recurrent "X in t" parts. *)
Notation RHS := (X in _ = X)%pattern.
diff --git a/toplevel/ccompile.ml b/toplevel/ccompile.ml
index 524f818523..b75a4199ea 100644
--- a/toplevel/ccompile.ml
+++ b/toplevel/ccompile.ml
@@ -139,7 +139,7 @@ let compile opts copts ~echo ~f_in ~f_out =
~aux_file:(aux_file_name_for long_f_dot_out)
~v_file:long_f_dot_in);
- Dumpglob.set_glob_output copts.glob_out;
+ Dumpglob.push_output copts.glob_out;
Dumpglob.start_dump_glob ~vfile:long_f_dot_in ~vofile:long_f_dot_out;
Dumpglob.dump_string ("F" ^ Names.DirPath.to_string ldir ^ "\n");
diff --git a/toplevel/coqargs.ml b/toplevel/coqargs.ml
index d587e57fd8..c6ccf2a427 100644
--- a/toplevel/coqargs.ml
+++ b/toplevel/coqargs.ml
@@ -266,8 +266,7 @@ let get_compat_file = function
| "8.13" -> "Coq.Compat.Coq813"
| "8.12" -> "Coq.Compat.Coq812"
| "8.11" -> "Coq.Compat.Coq811"
- | "8.10" -> "Coq.Compat.Coq810"
- | ("8.9" | "8.8" | "8.7" | "8.6" | "8.5" | "8.4" | "8.3" | "8.2" | "8.1" | "8.0") as s ->
+ | ("8.10" | "8.9" | "8.8" | "8.7" | "8.6" | "8.5" | "8.4" | "8.3" | "8.2" | "8.1" | "8.0") as s ->
CErrors.user_err ~hdr:"get_compat_file"
Pp.(str "Compatibility with version " ++ str s ++ str " not supported.")
| s ->
diff --git a/user-contrib/Ltac2/g_ltac2.mlg b/user-contrib/Ltac2/g_ltac2.mlg
index 6749169e8c..65b61a0d93 100644
--- a/user-contrib/Ltac2/g_ltac2.mlg
+++ b/user-contrib/Ltac2/g_ltac2.mlg
@@ -146,6 +146,8 @@ GRAMMAR EXTEND Gram
{ CAst.make ~loc @@ CTacLet (isrec, lc, e) }
| "match"; e = ltac2_expr LEVEL "5"; "with"; bl = branches; "end" ->
{ CAst.make ~loc @@ CTacCse (e, bl) }
+ | "if"; e = ltac2_expr LEVEL "5"; "then"; e1 = ltac2_expr LEVEL "5"; "else"; e2 = ltac2_expr LEVEL "5" ->
+ { CAst.make ~loc @@ CTacIft (e, e1, e2) }
]
| "4" LEFTA [ ]
| "3" [ e0 = SELF; ","; el = LIST1 NEXT SEP "," ->
diff --git a/user-contrib/Ltac2/tac2expr.mli b/user-contrib/Ltac2/tac2expr.mli
index 548655f561..0ae016265a 100644
--- a/user-contrib/Ltac2/tac2expr.mli
+++ b/user-contrib/Ltac2/tac2expr.mli
@@ -105,6 +105,7 @@ type raw_tacexpr_r =
| CTacLet of rec_flag * (raw_patexpr * raw_tacexpr) list * raw_tacexpr
| CTacCnv of raw_tacexpr * raw_typexpr
| CTacSeq of raw_tacexpr * raw_tacexpr
+| CTacIft of raw_tacexpr * raw_tacexpr * raw_tacexpr
| CTacCse of raw_tacexpr * raw_taccase list
| CTacRec of raw_recexpr
| CTacPrj of raw_tacexpr * ltac_projection or_relid
diff --git a/user-contrib/Ltac2/tac2intern.ml b/user-contrib/Ltac2/tac2intern.ml
index 797f72702d..ddf70a5a65 100644
--- a/user-contrib/Ltac2/tac2intern.ml
+++ b/user-contrib/Ltac2/tac2intern.ml
@@ -29,6 +29,7 @@ let t_string = coq_type "string"
let t_constr = coq_type "constr"
let t_ltac1 = ltac1_type "t"
let t_preterm = coq_type "preterm"
+let t_bool = coq_type "bool"
(** Union find *)
@@ -749,6 +750,15 @@ let rec intern_rec env {loc;v=e} = match e with
let (e2, t2) = intern_rec env e2 in
let () = check_elt_unit loc1 env t1 in
(GTacLet (false, [Anonymous, e1], e2), t2)
+| CTacIft (e, e1, e2) ->
+ let loc = e.loc in
+ let loc1 = e1.loc in
+ let (e, t) = intern_rec env e in
+ let (e1, t1) = intern_rec env e1 in
+ let (e2, t2) = intern_rec env e2 in
+ let () = unify ?loc env t (GTypRef (Other t_bool, [])) in
+ let () = unify ?loc:loc1 env t1 t2 in
+ (GTacCse (e, Other t_bool, [|e1; e2|], [||]), t2)
| CTacCse (e, pl) ->
intern_case env loc e pl
| CTacRec fs ->
@@ -1271,6 +1281,11 @@ let rec globalize ids ({loc;v=er} as e) = match er with
let e1 = globalize ids e1 in
let e2 = globalize ids e2 in
CAst.make ?loc @@ CTacSeq (e1, e2)
+| CTacIft (e, e1, e2) ->
+ let e = globalize ids e in
+ let e1 = globalize ids e1 in
+ let e2 = globalize ids e2 in
+ CAst.make ?loc @@ CTacIft (e, e1, e2)
| CTacCse (e, bl) ->
let e = globalize ids e in
let bl = List.map (fun b -> globalize_case ids b) bl in
@@ -1486,6 +1501,11 @@ let rec subst_rawexpr subst ({loc;v=tr} as t) = match tr with
let e1' = subst_rawexpr subst e1 in
let e2' = subst_rawexpr subst e2 in
if e1' == e1 && e2' == e2 then t else CAst.make ?loc @@ CTacSeq (e1', e2')
+| CTacIft (e, e1, e2) ->
+ let e' = subst_rawexpr subst e in
+ let e1' = subst_rawexpr subst e1 in
+ let e2' = subst_rawexpr subst e2 in
+ if e' == e && e1' == e1 && e2' == e2 then t else CAst.make ?loc @@ CTacIft (e', e1', e2')
| CTacCse (e, bl) ->
let map (p, e as x) =
let p' = subst_rawpattern subst p in
diff --git a/vernac/attributes.ml b/vernac/attributes.ml
index fb308fd316..efba6d332a 100644
--- a/vernac/attributes.ml
+++ b/vernac/attributes.ml
@@ -224,3 +224,11 @@ let canonical_field =
enable_attribute ~key:"canonical" ~default:(fun () -> true)
let canonical_instance =
enable_attribute ~key:"canonical" ~default:(fun () -> false)
+
+let uses_parser : string key_parser = fun orig args ->
+ assert_once ~name:"using" orig;
+ match args with
+ | VernacFlagLeaf str -> str
+ | _ -> CErrors.user_err (Pp.str "Ill formed \"using\" attribute")
+
+let using = attribute_of_list ["using",uses_parser]
diff --git a/vernac/attributes.mli b/vernac/attributes.mli
index 51bab79938..1969665082 100644
--- a/vernac/attributes.mli
+++ b/vernac/attributes.mli
@@ -51,6 +51,7 @@ val option_locality : Goptions.option_locality attribute
val deprecation : Deprecation.t option attribute
val canonical_field : bool attribute
val canonical_instance : bool attribute
+val using : string option attribute
val program_mode_option_name : string list
(** For internal use when messing with the global option. *)
diff --git a/vernac/classes.ml b/vernac/classes.ml
index d5509e2697..054addc542 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -57,7 +57,7 @@ let is_local_for_hint i =
let add_instance_base inst =
let locality = if is_local_for_hint inst then Goptions.OptLocal else Goptions.OptGlobal in
- add_instance_hint (Hints.IsGlobRef inst.is_impl) [inst.is_impl] ~locality
+ add_instance_hint (Hints.hint_globref inst.is_impl) [inst.is_impl] ~locality
inst.is_info
let mk_instance cl info glob impl =
@@ -503,7 +503,7 @@ let do_instance_program ~pm env env' sigma ?hook ~global ~poly cty k u ctx ctx'
declare_instance_program pm env sigma ~global ~poly id pri imps decl term termtype
let interp_instance_context ~program_mode env ctx ~generalize pl tclass =
- let sigma, decl = Constrexpr_ops.interp_univ_decl_opt env pl in
+ let sigma, decl = interp_univ_decl_opt env pl in
let tclass =
if generalize then CAst.make @@ CGeneralization (Glob_term.MaxImplicit, Some AbsPi, tclass)
else tclass
diff --git a/vernac/comAssumption.ml b/vernac/comAssumption.ml
index 12194ea20c..9e850ff1c7 100644
--- a/vernac/comAssumption.ml
+++ b/vernac/comAssumption.ml
@@ -13,7 +13,6 @@ open Util
open Vars
open Names
open Context
-open Constrexpr_ops
open Constrintern
open Impargs
open Pretyping
diff --git a/vernac/comDefinition.ml b/vernac/comDefinition.ml
index c1dbf0a1ea..81154bbea9 100644
--- a/vernac/comDefinition.ml
+++ b/vernac/comDefinition.ml
@@ -110,32 +110,42 @@ let interp_definition ~program_mode env evd impl_env bl red_option c ctypopt =
let tyopt = Option.map (fun ty -> EConstr.it_mkProd_or_LetIn ty ctx) tyopt in
evd, (c, tyopt), imps
-let do_definition ?hook ~name ~scope ~poly ~kind udecl bl red_option c ctypopt =
+let do_definition ?hook ~name ~scope ~poly ~kind ?using udecl bl red_option c ctypopt =
let program_mode = false in
let env = Global.env() in
(* Explicitly bound universes and constraints *)
- let evd, udecl = Constrexpr_ops.interp_univ_decl_opt env udecl in
+ let evd, udecl = interp_univ_decl_opt env udecl in
let evd, (body, types), impargs =
interp_definition ~program_mode env evd empty_internalization_env bl red_option c ctypopt
in
+ let using = using |> Option.map (fun expr ->
+ let terms = body :: match types with Some x -> [x] | None -> [] in
+ let l = Proof_using.process_expr (Global.env()) evd expr terms in
+ Names.Id.Set.(List.fold_right add l empty))
+ in
let kind = Decls.IsDefinition kind in
- let cinfo = Declare.CInfo.make ~name ~impargs ~typ:types () in
+ let cinfo = Declare.CInfo.make ~name ~impargs ~typ:types ?using () in
let info = Declare.Info.make ~scope ~kind ?hook ~udecl ~poly () in
let _ : Names.GlobRef.t =
Declare.declare_definition ~info ~cinfo ~opaque:false ~body evd
in ()
-let do_definition_program ?hook ~pm ~name ~scope ~poly ~kind udecl bl red_option c ctypopt =
+let do_definition_program ?hook ~pm ~name ~scope ~poly ~kind ?using udecl bl red_option c ctypopt =
let program_mode = true in
let env = Global.env() in
(* Explicitly bound universes and constraints *)
- let evd, udecl = Constrexpr_ops.interp_univ_decl_opt env udecl in
+ let evd, udecl = interp_univ_decl_opt env udecl in
let evd, (body, types), impargs =
interp_definition ~program_mode env evd empty_internalization_env bl red_option c ctypopt
in
+ let using = using |> Option.map (fun expr ->
+ let terms = body :: match types with Some x -> [x] | None -> [] in
+ let l = Proof_using.process_expr (Global.env()) evd expr terms in
+ Names.Id.Set.(List.fold_right add l empty))
+ in
let term, typ, uctx, obls = Declare.Obls.prepare_obligation ~name ~body ~types evd in
let pm, _ =
- let cinfo = Declare.CInfo.make ~name ~typ ~impargs () in
+ let cinfo = Declare.CInfo.make ~name ~typ ~impargs ?using () in
let info = Declare.Info.make ~udecl ~scope ~poly ~kind ?hook () in
Declare.Obls.add_definition ~pm ~cinfo ~info ~term ~uctx obls
in pm
diff --git a/vernac/comDefinition.mli b/vernac/comDefinition.mli
index 7420235449..5e1b705ae4 100644
--- a/vernac/comDefinition.mli
+++ b/vernac/comDefinition.mli
@@ -31,6 +31,7 @@ val do_definition
-> scope:Locality.locality
-> poly:bool
-> kind:Decls.definition_object_kind
+ -> ?using:Vernacexpr.section_subset_expr
-> universe_decl_expr option
-> local_binder_expr list
-> red_expr option
@@ -45,6 +46,7 @@ val do_definition_program
-> scope:Locality.locality
-> poly:bool
-> kind:Decls.logical_kind
+ -> ?using:Vernacexpr.section_subset_expr
-> universe_decl_expr option
-> local_binder_expr list
-> red_expr option
diff --git a/vernac/comFixpoint.ml b/vernac/comFixpoint.ml
index 78572c6aa6..dd6c985bf9 100644
--- a/vernac/comFixpoint.ml
+++ b/vernac/comFixpoint.ml
@@ -176,7 +176,7 @@ let interp_recursive ~program_mode ~cofix (fixl : 'a Vernacexpr.fix_expr_gen lis
if not (CList.for_all2eq (fun x y -> Id.equal x.CAst.v y.CAst.v) lsu usu) then
CErrors.user_err Pp.(str "(co)-recursive definitions should all have the same universe binders");
Some us) fixl None in
- let sigma, decl = Constrexpr_ops.interp_univ_decl_opt env all_universes in
+ let sigma, decl = interp_univ_decl_opt env all_universes in
let sigma, (fixctxs, fiximppairs, fixannots) =
on_snd List.split3 @@
List.fold_left_map (fun sigma -> interp_fix_context ~program_mode env sigma ~cofix) sigma fixl in
@@ -251,15 +251,22 @@ let interp_fixpoint ?(check_recursivity=true) ~cofix l :
let uctx,fix = ground_fixpoint env evd fix in
(fix,pl,uctx,info)
-let build_recthms ~indexes fixnames fixtypes fiximps =
+let build_recthms ~indexes ?using 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,_) ->
+ let using = using |> Option.map (fun expr ->
+ let terms = [EConstr.of_constr typ] in
+ let env = Global.env() in
+ let sigma = Evd.from_env env in
+ let l = Proof_using.process_expr env sigma expr terms in
+ Names.Id.Set.(List.fold_right add l empty))
+ in
let args = List.map Context.Rel.Declaration.get_name ctx in
- Declare.CInfo.make ~name ~typ ~args ~impargs ()
+ Declare.CInfo.make ~name ~typ ~args ~impargs ?using ()
) fixnames fixtypes fiximps
in
fix_kind, cofix, thms
@@ -277,9 +284,9 @@ 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),udecl,uctx,fiximps) ntns =
+let declare_fixpoint_generic ?indexes ~scope ~poly ?using ((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 fix_kind, cofix, fixitems = build_recthms ~indexes ?using fixnames fixtypes fiximps in
let fixdefs = List.map Option.get fixdefs in
let rec_declaration = prepare_recursive_declaration fixnames fixrs fixtypes fixdefs in
let fix_kind = Decls.IsDefinition fix_kind in
@@ -328,9 +335,9 @@ let do_fixpoint_interactive ~scope ~poly l : Declare.Proof.t =
let lemma = declare_fixpoint_interactive_generic ~indexes:possible_indexes ~scope ~poly fix ntns in
lemma
-let do_fixpoint ~scope ~poly l =
+let do_fixpoint ~scope ~poly ?using l =
let fixl, ntns, fix, possible_indexes = do_fixpoint_common l in
- declare_fixpoint_generic ~indexes:possible_indexes ~scope ~poly fix ntns
+ declare_fixpoint_generic ~indexes:possible_indexes ~scope ~poly ?using fix ntns
let do_cofixpoint_common (fixl : Vernacexpr.cofixpoint_expr list) =
let fixl = List.map (fun fix -> {fix with Vernacexpr.rec_order = None}) fixl in
@@ -342,6 +349,6 @@ let do_cofixpoint_interactive ~scope ~poly l =
let lemma = declare_fixpoint_interactive_generic ~scope ~poly cofix ntns in
lemma
-let do_cofixpoint ~scope ~poly l =
+let do_cofixpoint ~scope ~poly ?using l =
let cofix, ntns = do_cofixpoint_common l in
- declare_fixpoint_generic ~scope ~poly cofix ntns
+ declare_fixpoint_generic ~scope ~poly ?using cofix ntns
diff --git a/vernac/comFixpoint.mli b/vernac/comFixpoint.mli
index aa5446205c..a36aba7672 100644
--- a/vernac/comFixpoint.mli
+++ b/vernac/comFixpoint.mli
@@ -19,13 +19,13 @@ val do_fixpoint_interactive :
scope:Locality.locality -> poly:bool -> fixpoint_expr list -> Declare.Proof.t
val do_fixpoint :
- scope:Locality.locality -> poly:bool -> fixpoint_expr list -> unit
+ scope:Locality.locality -> poly:bool -> ?using:Vernacexpr.section_subset_expr -> fixpoint_expr list -> unit
val do_cofixpoint_interactive :
scope:Locality.locality -> poly:bool -> cofixpoint_expr list -> Declare.Proof.t
val do_cofixpoint :
- scope:Locality.locality -> poly:bool -> cofixpoint_expr list -> unit
+ scope:Locality.locality -> poly:bool -> ?using:Vernacexpr.section_subset_expr -> cofixpoint_expr list -> unit
(************************************************************************)
(** Internal API *)
diff --git a/vernac/comHints.ml b/vernac/comHints.ml
index 9eac558908..f642411fa4 100644
--- a/vernac/comHints.ml
+++ b/vernac/comHints.ml
@@ -62,7 +62,7 @@ let project_hint ~poly pri l2r r =
cb
in
let info = {Typeclasses.hint_priority = pri; hint_pattern = None} in
- (info, true, Hints.PathAny, Hints.IsGlobRef (GlobRef.ConstRef c))
+ (info, true, Hints.PathAny, Hints.hint_globref (GlobRef.ConstRef c))
let warn_deprecated_hint_constr =
CWarnings.create ~name:"fragile-hint-constr" ~category:"automation"
@@ -84,16 +84,6 @@ let soft_evaluable =
let interp_hints ~poly h =
let env = Global.env () in
let sigma = Evd.from_env env in
- let f poly c =
- let evd, c = Constrintern.interp_open_constr env sigma c in
- let env = Global.env () in
- let sigma = Evd.from_env env in
- let c, diff = Hints.prepare_hint true env sigma (evd, c) in
- if poly then (Hints.IsConstr (c, Some diff) [@ocaml.warning "-3"])
- else
- let () = DeclareUctx.declare_universe_context ~poly:false diff in
- (Hints.IsConstr (c, None) [@ocaml.warning "-3"])
- in
let fref r =
let gr = Smartlocate.global_with_alias r in
Dumpglob.add_glob ?loc:r.CAst.loc gr;
@@ -106,10 +96,22 @@ let interp_hints ~poly h =
match c with
| HintsReference c ->
let gr = Smartlocate.global_with_alias c in
- (PathHints [gr], IsGlobRef gr)
+ (PathHints [gr], hint_globref gr)
| HintsConstr c ->
let () = warn_deprecated_hint_constr () in
- (PathAny, f poly c)
+ let env = Global.env () in
+ let sigma = Evd.from_env env in
+ let c, uctx = Constrintern.interp_constr env sigma c in
+ let subst, uctx = UState.normalize_variables uctx in
+ let c = EConstr.Vars.subst_univs_constr subst c in
+ let diff = UState.context_set uctx in
+ let c =
+ if poly then (c, Some diff)
+ else
+ let () = DeclareUctx.declare_universe_context ~poly:false diff in
+ (c, None)
+ in
+ (PathAny, Hints.hint_constr c) [@ocaml.warning "-3"]
in
let fp = Constrintern.intern_constr_pattern env sigma in
let fres (info, b, r) =
@@ -149,7 +151,7 @@ let interp_hints ~poly h =
( empty_hint_info
, true
, PathHints [gr]
- , IsGlobRef gr ))
+ , hint_globref gr ))
in
HintsResolveEntry (List.flatten (List.map constr_hints_of_ind lqid))
| HintsExtern (pri, patcom, tacexp) ->
diff --git a/vernac/comPrimitive.ml b/vernac/comPrimitive.ml
index eaa5271a73..a910cc6e8b 100644
--- a/vernac/comPrimitive.ml
+++ b/vernac/comPrimitive.ml
@@ -30,7 +30,7 @@ let do_primitive id udecl prim typopt =
declare id {Entries.prim_entry_type = None; prim_entry_content = prim}
| Some typ ->
let env = Global.env () in
- let evd, udecl = Constrexpr_ops.interp_univ_decl_opt env udecl in
+ let evd, udecl = Constrintern.interp_univ_decl_opt env udecl in
let auctx = CPrimitives.op_or_type_univs prim in
let evd, u = Evd.with_context_set UState.univ_flexible evd (UnivGen.fresh_instance auctx) in
let expected_typ = EConstr.of_constr @@ Typeops.type_of_prim_or_type env u prim in
diff --git a/vernac/comProgramFixpoint.ml b/vernac/comProgramFixpoint.ml
index 55901fd604..31f91979d3 100644
--- a/vernac/comProgramFixpoint.ml
+++ b/vernac/comProgramFixpoint.ml
@@ -109,13 +109,13 @@ let telescope env sigma l =
let nf_evar_context sigma ctx =
List.map (map_constr (fun c -> Evarutil.nf_evar sigma c)) ctx
-let build_wellfounded pm (recname,pl,bl,arityc,body) poly r measure notation =
+let build_wellfounded pm (recname,pl,bl,arityc,body) poly ?using r measure notation =
let open EConstr in
let open Vars in
let lift_rel_context n l = Termops.map_rel_context_with_binders (liftn n) l in
Coqlib.check_required_library ["Coq";"Program";"Wf"];
let env = Global.env() in
- let sigma, udecl = Constrexpr_ops.interp_univ_decl_opt env pl in
+ let sigma, udecl = interp_univ_decl_opt env pl in
let sigma, (_, ((env', binders_rel), impls)) = interp_context_evars ~program_mode:true env sigma bl in
let len = List.length binders_rel in
let top_env = push_rel_context binders_rel env in
@@ -259,8 +259,13 @@ let build_wellfounded pm (recname,pl,bl,arityc,body) poly r measure notation =
let evars, _, evars_def, evars_typ =
RetrieveObl.retrieve_obligations env recname sigma 0 def typ
in
+ let using = using |> Option.map (fun expr ->
+ let terms = List.map EConstr.of_constr [evars_def; evars_typ] in
+ let l = Proof_using.process_expr env sigma expr terms in
+ Names.Id.Set.(List.fold_right add l empty))
+ in
let uctx = Evd.evar_universe_context sigma in
- let cinfo = Declare.CInfo.make ~name:recname ~typ:evars_typ () in
+ let cinfo = Declare.CInfo.make ~name:recname ~typ:evars_typ ?using () in
let info = Declare.Info.make ~udecl ~poly ~hook () in
let pm, _ =
Declare.Obls.add_definition ~pm ~cinfo ~info ~term:evars_def ~uctx evars in
@@ -275,7 +280,7 @@ let collect_evars_of_term evd c ty =
Evar.Set.fold (fun ev acc -> Evd.add acc ev (Evd.find_undefined evd ev))
evars (Evd.from_ctx (Evd.evar_universe_context evd))
-let do_program_recursive ~pm ~scope ~poly fixkind fixl =
+let do_program_recursive ~pm ~scope ~poly ?using fixkind fixl =
let cofix = fixkind = Declare.Obls.IsCoFixpoint in
let (env, rec_sign, udecl, evd), fix, info =
interp_recursive ~cofix ~program_mode:true fixl
@@ -287,13 +292,18 @@ let do_program_recursive ~pm ~scope ~poly fixkind fixl =
let evd = nf_evar_map_undefined evd in
let collect_evars name def typ impargs =
(* Generalize by the recursive prototypes *)
+ let using = using |> Option.map (fun expr ->
+ let terms = [def; typ] in
+ let l = Proof_using.process_expr env evd expr terms in
+ Names.Id.Set.(List.fold_right add l empty))
+ in
let def = nf_evar evd (Termops.it_mkNamedLambda_or_LetIn def rec_sign) in
let typ = nf_evar evd (Termops.it_mkNamedProd_or_LetIn typ rec_sign) in
let evm = collect_evars_of_term evd def typ in
let evars, _, def, typ =
RetrieveObl.retrieve_obligations env name evm
(List.length rec_sign) def typ in
- let cinfo = Declare.CInfo.make ~name ~typ ~impargs () in
+ let cinfo = Declare.CInfo.make ~name ~typ ~impargs ?using () in
(cinfo, def, evars)
in
let (fixnames,fixrs,fixdefs,fixtypes) = fix in
@@ -325,13 +335,13 @@ let do_program_recursive ~pm ~scope ~poly fixkind fixl =
let info = Declare.Info.make ~poly ~scope ~kind ~udecl () in
Declare.Obls.add_mutual_definitions ~pm defs ~info ~uctx ~ntns fixkind
-let do_fixpoint ~pm ~scope ~poly l =
+let do_fixpoint ~pm ~scope ~poly ?using l =
let g = List.map (fun { Vernacexpr.rec_order } -> rec_order) l in
match g, l with
| [Some { CAst.v = CWfRec (n,r) }],
[ Vernacexpr.{fname={CAst.v=id}; univs; binders; rtype; body_def; notations} ] ->
let recarg = mkIdentC n.CAst.v in
- build_wellfounded pm (id, univs, binders, rtype, out_def body_def) poly r recarg notations
+ build_wellfounded pm (id, univs, binders, rtype, out_def body_def) poly ?using r recarg notations
| [Some { CAst.v = CMeasureRec (n, m, r) }],
[Vernacexpr.{fname={CAst.v=id}; univs; binders; rtype; body_def; notations }] ->
@@ -344,7 +354,7 @@ let do_fixpoint ~pm ~scope ~poly l =
user_err Pp.(str"Measure takes only two arguments in Program Fixpoint.")
| _, _ -> r
in
- build_wellfounded pm (id, univs, binders, rtype, out_def body_def) poly
+ build_wellfounded pm (id, univs, binders, rtype, out_def body_def) poly ?using
(Option.default (CAst.make @@ CRef (lt_ref,None)) r) m notations
| _, _ when List.for_all (fun ro -> match ro with None | Some { CAst.v = CStructRec _} -> true | _ -> false) g ->
@@ -352,11 +362,11 @@ let do_fixpoint ~pm ~scope ~poly l =
Vernacexpr.(ComFixpoint.adjust_rec_order ~structonly:true fix.binders fix.rec_order)) l in
let fixkind = Declare.Obls.IsFixpoint annots in
let l = List.map2 (fun fix rec_order -> { fix with Vernacexpr.rec_order }) l annots in
- do_program_recursive ~pm ~scope ~poly fixkind l
+ do_program_recursive ~pm ~scope ~poly ?using fixkind l
| _, _ ->
CErrors.user_err ~hdr:"do_fixpoint"
(str "Well-founded fixpoints not allowed in mutually recursive blocks")
-let do_cofixpoint ~pm ~scope ~poly fixl =
+let do_cofixpoint ~pm ~scope ~poly ?using fixl =
let fixl = List.map (fun fix -> { fix with Vernacexpr.rec_order = None }) fixl in
- do_program_recursive ~pm ~scope ~poly Declare.Obls.IsCoFixpoint fixl
+ do_program_recursive ~pm ~scope ~poly ?using Declare.Obls.IsCoFixpoint fixl
diff --git a/vernac/comProgramFixpoint.mli b/vernac/comProgramFixpoint.mli
index 7935cf27fb..30bf3ae8f8 100644
--- a/vernac/comProgramFixpoint.mli
+++ b/vernac/comProgramFixpoint.mli
@@ -15,6 +15,7 @@ val do_fixpoint :
pm:Declare.OblState.t
-> scope:Locality.locality
-> poly:bool
+ -> ?using:Vernacexpr.section_subset_expr
-> fixpoint_expr list
-> Declare.OblState.t
@@ -22,5 +23,6 @@ val do_cofixpoint :
pm:Declare.OblState.t
-> scope:Locality.locality
-> poly:bool
+ -> ?using:Vernacexpr.section_subset_expr
-> cofixpoint_expr list
-> Declare.OblState.t
diff --git a/vernac/comSearch.ml b/vernac/comSearch.ml
index 9de8d6fbc3..af51f4fafb 100644
--- a/vernac/comSearch.ml
+++ b/vernac/comSearch.ml
@@ -53,9 +53,19 @@ let kind_searcher = Decls.(function
let interp_search_item env sigma =
function
| SearchSubPattern ((where,head),pat) ->
- let _,pat = Constrintern.intern_constr_pattern env sigma pat in
+ let expected_type = Pretyping.(if head then IsType else WithoutTypeConstraint) in
+ let pat =
+ try Constrintern.interp_constr_pattern env sigma ~expected_type pat
+ with e when CErrors.noncritical e ->
+ (* We cannot ensure (yet?) that a typable pattern will
+ actually be typed, consider e.g. (forall A, A -> A /\ A)
+ which fails, not seeing that A can be Prop; so we use an
+ untyped pattern as a fallback (i.e w/o no insertion of
+ coercions, no compilation of pattern-matching) *)
+ snd (Constrintern.intern_constr_pattern env sigma ~as_type:head pat) in
GlobSearchSubPattern (where,head,pat)
- | SearchString ((Anywhere,false),s,None) when Id.is_valid s ->
+ | SearchString ((Anywhere,false),s,None)
+ when Id.is_valid_ident_part s && String.equal (String.drop_simple_quotes s) s ->
GlobSearchString s
| SearchString ((where,head),s,sc) ->
(try
diff --git a/vernac/declare.ml b/vernac/declare.ml
index 3a8ceb0e0f..1e8771b641 100644
--- a/vernac/declare.ml
+++ b/vernac/declare.ml
@@ -55,11 +55,13 @@ module CInfo = struct
(** Names to pre-introduce *)
; impargs : Impargs.manual_implicits
(** Explicitily declared implicit arguments *)
+ ; using : Names.Id.Set.t option
+ (** Explicit declaration of section variables used by the constant *)
}
- let make ~name ~typ ?(args=[]) ?(impargs=[]) () =
- { name; typ; args; impargs }
+ let make ~name ~typ ?(args=[]) ?(impargs=[]) ?using () =
+ { name; typ; args; impargs; using }
let to_constr sigma thm = { thm with typ = EConstr.to_constr sigma thm.typ }
@@ -108,10 +110,10 @@ let default_univ_entry = Entries.Monomorphic_entry Univ.ContextSet.empty
(** [univsbody] are universe-constraints attached to the body-only,
used in vio-delayed opaque constants and private poly universes *)
-let definition_entry_core ?(opaque=false) ?(inline=false) ?feedback_id ?section_vars ?types
+let definition_entry_core ?(opaque=false) ?using ?(inline=false) ?feedback_id ?types
?(univs=default_univ_entry) ?(eff=Evd.empty_side_effects) ?(univsbody=Univ.ContextSet.empty) body =
{ proof_entry_body = Future.from_val ((body,univsbody), eff);
- proof_entry_secctx = section_vars;
+ proof_entry_secctx = using;
proof_entry_type = types;
proof_entry_universes = univs;
proof_entry_opaque = opaque;
@@ -119,7 +121,7 @@ let definition_entry_core ?(opaque=false) ?(inline=false) ?feedback_id ?section_
proof_entry_inline_code = inline}
let definition_entry =
- definition_entry_core ?eff:None ?univsbody:None ?feedback_id:None ?section_vars:None
+ definition_entry_core ?eff:None ?univsbody:None ?feedback_id:None
type 'a constant_entry =
| DefinitionEntry of 'a proof_entry
@@ -236,9 +238,9 @@ let pure_definition_entry ?(opaque=false) ?(inline=false) ?types
proof_entry_feedback = None;
proof_entry_inline_code = inline}
-let delayed_definition_entry ~opaque ?feedback_id ~section_vars ~univs ?types body =
+let delayed_definition_entry ~opaque ?feedback_id ~using ~univs ?types body =
{ proof_entry_body = body
- ; proof_entry_secctx = section_vars
+ ; proof_entry_secctx = using
; proof_entry_type = types
; proof_entry_universes = univs
; proof_entry_opaque = opaque
@@ -608,8 +610,8 @@ let declare_mutually_recursive_core ~info ~cinfo ~opaque ~ntns ~uctx ~rec_declar
uctx, univs
in
let csts = CList.map2
- (fun CInfo.{ name; typ; impargs } body ->
- let entry = definition_entry ~opaque ~types:typ ~univs body in
+ (fun CInfo.{ name; typ; impargs; using } body ->
+ let entry = definition_entry ~opaque ~types:typ ~univs ?using body in
declare_entry ~name ~scope ~kind ~impargs ~uctx entry)
cinfo fixdecls
in
@@ -660,7 +662,7 @@ let check_evars_are_solved env sigma t =
let evars = Evarutil.undefined_evars_of_term sigma t in
if not (Evar.Set.is_empty evars) then error_unresolved_evars env sigma t evars
-let prepare_definition ~info ~opaque ~body ~typ sigma =
+let prepare_definition ~info ~opaque ?using ~body ~typ sigma =
let { Info.poly; udecl; inline; _ } = info in
let env = Global.env () in
let sigma, (body, types) = Evarutil.finalize ~abort_on_undefined_evars:false
@@ -669,13 +671,13 @@ let prepare_definition ~info ~opaque ~body ~typ sigma =
Option.iter (check_evars_are_solved env sigma) types;
check_evars_are_solved env sigma body;
let univs = Evd.check_univ_decl ~poly sigma udecl in
- let entry = definition_entry ~opaque ~inline ?types ~univs body in
+ let entry = definition_entry ~opaque ?using ~inline ?types ~univs body in
let uctx = Evd.evar_universe_context sigma in
entry, uctx
let declare_definition_core ~info ~cinfo ~opaque ~obls ~body sigma =
- let { CInfo.name; impargs; typ; _ } = cinfo in
- let entry, uctx = prepare_definition ~info ~opaque ~body ~typ sigma in
+ let { CInfo.name; impargs; typ; using; _ } = cinfo in
+ let entry, uctx = prepare_definition ~info ~opaque ?using ~body ~typ sigma in
let { Info.scope; kind; hook; _ } = info in
declare_entry_core ~name ~scope ~kind ~impargs ~obls ?hook ~uctx entry, uctx
@@ -803,6 +805,7 @@ module ProgramDecl = struct
let set_uctx ~uctx prg = {prg with prg_uctx = uctx}
let get_poly prg = prg.prg_info.Info.poly
let get_obligations prg = prg.prg_obligations
+ let get_using prg = prg.prg_cinfo.CInfo.using
end
end
@@ -1137,7 +1140,7 @@ let declare_mutual_definition ~pm l =
in
let term = EConstr.to_constr sigma term in
let typ = EConstr.to_constr sigma typ in
- let def = (x.prg_reduce term, r, x.prg_reduce typ, x.prg_cinfo.CInfo.impargs) in
+ let def = (x.prg_reduce term, r, x.prg_reduce typ, x.prg_cinfo.CInfo.impargs, x.prg_cinfo.CInfo.using) in
let oblsubst = List.map (fun (id, (_, c)) -> (id, c)) oblsubst in
(def, oblsubst)
in
@@ -1151,11 +1154,11 @@ let declare_mutual_definition ~pm l =
(* let fixdefs = List.map reduce_fix fixdefs in *)
let fixdefs, fixrs, fixtypes, fixitems =
List.fold_right2
- (fun (d, r, typ, impargs) name (a1, a2, a3, a4) ->
+ (fun (d, r, typ, impargs, using) name (a1, a2, a3, a4) ->
( d :: a1
, r :: a2
, typ :: a3
- , CInfo.{name; typ; impargs; args = []} :: a4 ))
+ , CInfo.{name; typ; impargs; args = []; using } :: a4 ))
defs first.prg_deps ([], [], [], [])
in
let fixkind = Option.get first.prg_fixkind in
@@ -1288,7 +1291,7 @@ let obligation_terminator ~pm ~entry ~uctx ~oinfo:{name; num; auto} =
FIXME: There is duplication of this code with obligation_terminator
and Obligations.admit_obligations *)
-let obligation_admitted_terminator ~pm {name; num; auto} ctx' dref =
+let obligation_admitted_terminator ~pm {name; num; auto} uctx' dref =
let prg = Option.get (State.find pm name) in
let {obls; remaining = rem} = prg.prg_obligations in
let obl = obls.(num) in
@@ -1300,21 +1303,21 @@ let obligation_admitted_terminator ~pm {name; num; auto} ctx' dref =
if not transparent then err_not_transp ()
| _ -> ()
in
- let inst, ctx' =
+ let inst, uctx' =
if not prg.prg_info.Info.poly (* Not polymorphic *) then
(* The universe context was declared globally, we continue
from the new global environment. *)
- let ctx = UState.from_env (Global.env ()) in
- let ctx' = UState.merge_subst ctx (UState.subst ctx') in
- (Univ.Instance.empty, ctx')
+ let uctx = UState.from_env (Global.env ()) in
+ let uctx' = UState.merge_subst uctx (UState.subst uctx') in
+ (Univ.Instance.empty, uctx')
else
(* We get the right order somehow, but surely it could be enforced in a clearer way. *)
- let uctx = UState.context ctx' in
- (Univ.UContext.instance uctx, ctx')
+ let uctx = UState.context uctx' in
+ (Univ.UContext.instance uctx, uctx')
in
let obl = {obl with obl_body = Some (DefinedObl (cst, inst))} in
let () = if transparent then add_hint true prg cst in
- update_program_decl_on_defined ~pm prg obls num obl ~uctx:ctx' rem ~auto
+ update_program_decl_on_defined ~pm prg obls num obl ~uctx:uctx' rem ~auto
end
@@ -1376,7 +1379,7 @@ end
type t =
{ endline_tactic : Genarg.glob_generic_argument option
- ; section_vars : Id.Set.t option
+ ; using : Id.Set.t option
; proof : Proof.t
; initial_euctx : UState.t
(** The initial universe context (for the statement) *)
@@ -1435,7 +1438,7 @@ let start_proof_core ~name ~typ ~pinfo ?(sign=initialize_named_context_for_proof
let initial_euctx = Evd.evar_universe_context Proof.((data proof).sigma) in
{ proof
; endline_tactic = None
- ; section_vars = None
+ ; using = None
; initial_euctx
; pinfo
}
@@ -1458,7 +1461,7 @@ let start_dependent ~info ~name ~proof_ending goals =
let pinfo = Proof_info.make ~info ~cinfo ~proof_ending () in
{ proof
; endline_tactic = None
- ; section_vars = None
+ ; using = None
; initial_euctx
; pinfo
}
@@ -1523,7 +1526,7 @@ let start_mutual_with_initialization ~info ~cinfo ~mutual_info sigma snl =
map lemma ~f:(fun p ->
pi1 @@ Proof.run_tactic Global.(env ()) init_tac p)
-let get_used_variables pf = pf.section_vars
+let get_used_variables pf = pf.using
let get_universe_decl pf = pf.pinfo.Proof_info.info.Info.udecl
let set_used_variables ps l =
@@ -1547,9 +1550,9 @@ let set_used_variables ps l =
else (ctx, all_safe) in
let ctx, _ =
Environ.fold_named_context aux env ~init:(ctx,ctx_set) in
- if not (Option.is_empty ps.section_vars) then
+ if not (Option.is_empty ps.using) then
CErrors.user_err Pp.(str "Used section variables can be declared only once");
- ctx, { ps with section_vars = Some (Context.Named.to_vars ctx) }
+ ctx, { ps with using = Some (Context.Named.to_vars ctx) }
let get_open_goals ps =
let Proof.{ goals; stack; sigma } = Proof.data ps.proof in
@@ -1624,12 +1627,12 @@ let make_univs_deferred ~poly ~initial_euctx ~uctx ~udecl
let make_univs_private_poly ~poly ~uctx ~udecl (used_univs_typ, typ) (used_univs_body, body) =
let used_univs = Univ.LSet.union used_univs_body used_univs_typ in
- let universes = UState.restrict uctx used_univs in
- let typus = UState.restrict universes used_univs_typ in
- let utyp = UState.check_univ_decl ~poly typus udecl in
+ let uctx = UState.restrict uctx used_univs in
+ let uctx' = UState.restrict uctx used_univs_typ in
+ let utyp = UState.check_univ_decl ~poly uctx' udecl in
let ubody = Univ.ContextSet.diff
- (UState.context_set universes)
- (UState.context_set typus)
+ (UState.context_set uctx)
+ (UState.context_set uctx')
in
utyp, ubody
@@ -1640,13 +1643,13 @@ let make_univs ~poly ~uctx ~udecl (used_univs_typ, typ) (used_univs_body, body)
for the typ. We recheck the declaration after restricting with
the actually used universes.
TODO: check if restrict is really necessary now. *)
- let ctx = UState.restrict uctx used_univs in
- let utyp = UState.check_univ_decl ~poly ctx udecl in
+ let uctx = UState.restrict uctx used_univs in
+ let utyp = UState.check_univ_decl ~poly uctx udecl in
utyp, Univ.ContextSet.empty
let close_proof ~opaque ~keep_body_ucst_separate ps =
- let { section_vars; proof; initial_euctx; pinfo } = ps in
+ let { using; proof; initial_euctx; pinfo } = ps in
let { Proof_info.info = { Info.udecl } } = pinfo in
let { Proof.name; poly } = Proof.data proof in
let unsafe_typ = keep_body_ucst_separate && not poly in
@@ -1667,7 +1670,7 @@ let close_proof ~opaque ~keep_body_ucst_separate ps =
then make_univs_private_poly ~poly ~uctx ~udecl t b
else make_univs ~poly ~uctx ~udecl t b
in
- definition_entry_core ~opaque ?section_vars ~univs:utyp ~univsbody:ubody ~types:typ ~eff body
+ definition_entry_core ~opaque ?using ~univs:utyp ~univsbody:ubody ~types:typ ~eff body
in
let entries = CList.map make_entry elist in
{ name; entries; uctx }
@@ -1675,7 +1678,7 @@ let close_proof ~opaque ~keep_body_ucst_separate ps =
type closed_proof_output = (Constr.t * Evd.side_effects) list * UState.t
let close_proof_delayed ~feedback_id ps (fpl : closed_proof_output Future.computation) =
- let { section_vars; proof; initial_euctx; pinfo } = ps in
+ let { using; proof; initial_euctx; pinfo } = ps in
let { Proof_info.info = { Info.udecl } } = pinfo in
let { Proof.name; poly; entry; sigma } = Proof.data proof in
@@ -1709,10 +1712,10 @@ let close_proof_delayed ~feedback_id ps (fpl : closed_proof_output Future.comput
(Vars.universes_of_constr types)
(Vars.universes_of_constr pt)
in
- let univs = UState.restrict uctx used_univs in
- let univs = UState.check_mono_univ_decl univs udecl in
- (pt,univs),eff)
- |> delayed_definition_entry ~opaque ~feedback_id ~section_vars ~univs ~types
+ let uctx = UState.restrict uctx used_univs in
+ let uctx = UState.check_mono_univ_decl uctx udecl in
+ (pt,uctx),eff)
+ |> delayed_definition_entry ~opaque ~feedback_id ~using ~univs ~types
in
let entries = Future.map2 make_entry fpl (Proofview.initial_goals entry) in
{ name; entries; uctx = initial_euctx }
@@ -2289,7 +2292,8 @@ let rec solve_obligation prg num tac =
let name = Internal.get_name prg in
Proof_ending.End_obligation {name; num; auto}
in
- let cinfo = CInfo.make ~name:obl.obl_name ~typ:(EConstr.of_constr obl.obl_type) () in
+ let using = Internal.get_using prg in
+ let cinfo = CInfo.make ~name:obl.obl_name ~typ:(EConstr.of_constr obl.obl_type) ?using () in
let poly = Internal.get_poly prg in
let info = Info.make ~scope ~kind ~poly () in
let lemma = Proof.start_core ~cinfo ~info ~proof_ending evd in
@@ -2495,7 +2499,12 @@ let admit_obligations ~pm n =
let next_obligation ~pm n tac =
let prg = match n with
- | None -> State.first_pending pm |> Option.get
+ | None ->
+ begin match State.first_pending pm with
+ | Some prg -> prg
+ | None ->
+ Error.no_obligations None
+ end
| Some _ -> get_unique_prog ~pm n
in
let {obls; remaining} = Internal.get_obligations prg in
diff --git a/vernac/declare.mli b/vernac/declare.mli
index 1ad79928d5..0520bf8717 100644
--- a/vernac/declare.mli
+++ b/vernac/declare.mli
@@ -79,6 +79,7 @@ module CInfo : sig
-> typ:'constr
-> ?args:Name.t list
-> ?impargs:Impargs.manual_implicits
+ -> ?using:Names.Id.Set.t
-> unit
-> 'constr t
@@ -244,6 +245,12 @@ module Proof : sig
* (w.r.t. type dependencies and let-ins covered by it) *)
val set_used_variables : t -> Names.Id.t list -> Constr.named_context * t
+ (** Gets the set of variables declared to be used by the proof. None means
+ no "Proof using" or #[using] was given *)
+ val get_used_variables : t -> Id.Set.t option
+
+ (** Compacts the representation of the proof by pruning all intermediate
+ terms *)
val compact : t -> t
(** Update the proof's universe information typically after a
@@ -333,6 +340,7 @@ type 'a proof_entry
val definition_entry
: ?opaque:bool
+ -> ?using:Names.Id.Set.t
-> ?inline:bool
-> ?types:Constr.types
-> ?univs:Entries.universes_entry
diff --git a/vernac/declaremods.mli b/vernac/declaremods.mli
index 9ca2ca5593..a1b98e4d9c 100644
--- a/vernac/declaremods.mli
+++ b/vernac/declaremods.mli
@@ -86,7 +86,7 @@ val start_library : library_name -> unit
val end_library :
?except:Future.UUIDSet.t -> output_native_objects:bool -> library_name ->
- Safe_typing.compiled_library * library_objects * Safe_typing.native_library
+ Safe_typing.compiled_library * library_objects * Nativelib.native_library
(** append a function to be executed at end_library *)
val append_end_library_hook : (unit -> unit) -> unit
diff --git a/vernac/egramcoq.ml b/vernac/egramcoq.ml
index 123ea2c24e..efe4e17d0b 100644
--- a/vernac/egramcoq.ml
+++ b/vernac/egramcoq.ml
@@ -408,8 +408,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 (NumTok.Signed.of_int_string v)))
- | ForPattern -> push_constr subst (CAst.make @@ CPatPrim (Numeral (NumTok.Signed.of_int_string v)))
+ | ForConstr -> push_constr subst (CAst.make @@ CPrim (Number (NumTok.Signed.of_int_string v)))
+ | ForPattern -> push_constr subst (CAst.make @@ CPatPrim (Number (NumTok.Signed.of_int_string v)))
end
| TTReference ->
begin match forpat with
diff --git a/vernac/g_proofs.mlg b/vernac/g_proofs.mlg
index ebec720ce2..5b80ed6794 100644
--- a/vernac/g_proofs.mlg
+++ b/vernac/g_proofs.mlg
@@ -56,6 +56,8 @@ GRAMMAR EXTEND Gram
[ [ IDENT "Goal"; c = lconstr ->
{ VernacDefinition (Decls.(NoDischarge, Definition), ((CAst.make ~loc Names.Anonymous), None), ProveBody ([], c)) }
| IDENT "Proof" -> { VernacProof (None,None) }
+ | IDENT "Proof"; IDENT "using"; l = G_vernac.section_subset_expr ->
+ { VernacProof (None,Some l) }
| IDENT "Proof" ; IDENT "Mode" ; mn = string -> { VernacProofMode mn }
| IDENT "Proof"; c = lconstr -> { VernacExactProof c }
| IDENT "Abort" -> { VernacAbort None }
diff --git a/vernac/g_vernac.mlg b/vernac/g_vernac.mlg
index 3d6a93c888..1c80d71ea5 100644
--- a/vernac/g_vernac.mlg
+++ b/vernac/g_vernac.mlg
@@ -113,7 +113,9 @@ GRAMMAR EXTEND Gram
]
;
attribute:
- [ [ k = ident ; v = attr_value -> { Names.Id.to_string k, v } ]
+ [ [ k = ident ; v = attr_value -> { Names.Id.to_string k, v }
+ (* Required because "ident" is declared a keyword when loading Ltac. *)
+ | IDENT "using" ; v = attr_value -> { "using", v } ]
]
;
attr_value:
diff --git a/vernac/library.ml b/vernac/library.ml
index e580927bfd..8a9b1fd68d 100644
--- a/vernac/library.ml
+++ b/vernac/library.ml
@@ -160,7 +160,7 @@ let register_loaded_library m =
let prefix = Nativecode.mod_uid_of_dirpath libname ^ "." in
let f = prefix ^ "cmo" in
let f = Dynlink.adapt_filename f in
- Nativelib.link_library (Global.env()) ~prefix ~dirname ~basename:f
+ Nativelib.link_library ~prefix ~dirname ~basename:f
in
let rec aux = function
| [] ->
@@ -502,7 +502,7 @@ let save_library_to todo_proofs ~output_native_objects dir f otab =
(* Writing native code files *)
if output_native_objects then
let fn = Filename.dirname f ^"/"^ Nativecode.mod_uid_of_dirpath dir in
- Nativelib.compile_library dir ast fn
+ Nativelib.compile_library ast fn
let save_library_raw f sum lib univs proofs =
save_library_base f sum lib (Some univs) None proofs
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index 185abcf35b..8477870cb4 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -1042,6 +1042,13 @@ let interp_non_syntax_modifiers mods =
in
List.fold_left (fun st modif -> Option.bind st @@ set modif) (Some (false,false,InConstrEntry)) mods
+(* Check if an interpretation can be used for printing a cases printing *)
+let has_no_binders_type =
+ List.for_all (fun (_,(_,typ)) ->
+ match typ with
+ | NtnTypeBinder _ | NtnTypeBinderList -> false
+ | NtnTypeConstr | NtnTypeConstrList -> true)
+
(* Compute precedences from modifiers (or find default ones) *)
let set_entry_type from n etyps (x,typ) =
@@ -1226,6 +1233,9 @@ let find_precedence custom lev etyps symbols onlyprint =
| _ ->
user_err Pp.(str "A notation starting with an atomic expression must be at level 0.")
end
+ | (ETPattern _ | ETBinder _), InConstrEntry when not onlyprint ->
+ (* Don't know exactly if we can make sense of this case *)
+ user_err Pp.(str "Binders or patterns not supported in leftmost position.")
| (ETPattern _ | ETBinder _ | ETConstr _), _ ->
(* Give a default ? *)
if Option.is_empty lev then
@@ -1416,6 +1426,7 @@ type notation_obj = {
notobj_deprecation : Deprecation.t option;
notobj_notation : notation * notation_location;
notobj_specific_pp_rules : syntax_printing_extension option;
+ notobj_also_in_cases_pattern : bool;
}
let load_notation_common silently_define_scope_if_undefined _ (_, nobj) =
@@ -1438,9 +1449,10 @@ let open_notation i (_, nobj) =
let pat = nobj.notobj_interp in
let deprecation = nobj.notobj_deprecation in
let scope = match scope with None -> LastLonelyNotation | Some sc -> NotationInScope sc in
+ let also_in_cases_pattern = nobj.notobj_also_in_cases_pattern in
(* Declare the notation *)
(match nobj.notobj_use with
- | Some use -> Notation.declare_notation (scope,ntn) pat df ~use nobj.notobj_coercion deprecation
+ | Some use -> Notation.declare_notation (scope,ntn) pat df ~use ~also_in_cases_pattern nobj.notobj_coercion deprecation
| None -> ());
(* Declare specific format if any *)
(match nobj.notobj_specific_pp_rules with
@@ -1621,19 +1633,21 @@ let add_notation_in_scope ~local deprecation df env c mods scope =
let (acvars, ac, reversibility) = interp_notation_constr env nenv c in
let interp = make_interpretation_vars sd.recvars (pi2 sd.level) acvars (fst sd.pa_syntax_data) in
let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in
+ let vars = List.map_filter map i_vars in (* Order of elements is important here! *)
+ let also_in_cases_pattern = has_no_binders_type vars in
let onlyparse,coe = printability (Some sd.level) sd.subentries sd.only_parsing reversibility ac in
let notation, location = sd.info in
let use = make_use true onlyparse sd.only_printing in
let notation = {
notobj_local = local;
notobj_scope = scope;
- notobj_interp = (List.map_filter map i_vars, ac);
- (* Order is important here! *)
notobj_use = use;
+ notobj_interp = (vars, ac);
notobj_coercion = coe;
notobj_deprecation = sd.deprecation;
notobj_notation = (notation, location);
notobj_specific_pp_rules = sy_pp_rules;
+ notobj_also_in_cases_pattern = also_in_cases_pattern;
} in
(* Ready to change the global state *)
List.iter (fun f -> f ()) sd.msgs;
@@ -1665,18 +1679,20 @@ let add_notation_interpretation_core ~local df env ?(impls=empty_internalization
let plevel = match level with Some (from,level,l) -> level | None (* numeral: irrelevant )*) -> 0 in
let interp = make_interpretation_vars recvars plevel acvars (List.combine mainvars i_typs) in
let map (x, _) = try Some (x, Id.Map.find x interp) with Not_found -> None in
+ let vars = List.map_filter map i_vars in (* Order of elements is important here! *)
+ let also_in_cases_pattern = has_no_binders_type vars in
let onlyparse,coe = printability level i_typs onlyparse reversibility ac in
let use = make_use false onlyparse onlyprint in
let notation = {
notobj_local = local;
notobj_scope = scope;
- notobj_interp = (List.map_filter map i_vars, ac);
- (* Order is important here! *)
notobj_use = use;
+ notobj_interp = (vars, ac);
notobj_coercion = coe;
notobj_deprecation = deprecation;
notobj_notation = df';
notobj_specific_pp_rules = pp_sy;
+ notobj_also_in_cases_pattern = also_in_cases_pattern;
} in
Lib.add_anonymous_leaf (inNotation notation);
df'
@@ -1850,8 +1866,9 @@ let add_syntactic_definition ~local deprecation env ident (vars,c) { onlyparsing
let in_pat id = (id,ETConstr (Constrexpr.InConstrEntry,None,(NextLevel,InternalProd))) in
let interp = make_interpretation_vars ~default_if_binding:AsIdentOrPattern [] 0 acvars (List.map in_pat vars) in
let vars = List.map (fun x -> (x, Id.Map.find x interp)) vars in
+ let also_in_cases_pattern = has_no_binders_type vars in
let onlyparsing = onlyparsing || fst (printability None [] false reversibility pat) in
- Syntax_def.declare_syntactic_definition ~local deprecation ident ~onlyparsing (vars,pat)
+ Syntax_def.declare_syntactic_definition ~local ~also_in_cases_pattern deprecation ident ~onlyparsing (vars,pat)
(**********************************************************************)
(* Declaration of custom entry *)
diff --git a/vernac/prettyp.ml b/vernac/prettyp.ml
index 06f7c32cdc..840754ccc6 100644
--- a/vernac/prettyp.ml
+++ b/vernac/prettyp.ml
@@ -631,11 +631,11 @@ let print_constant with_values sep sp udecl =
assert(ContextSet.is_empty body_uctxs);
Polymorphic ctx
in
- let ctx =
+ let uctx =
UState.of_binders
(Printer.universe_binders_with_opt_names (Declareops.constant_polymorphic_context cb) udecl)
in
- let env = Global.env () and sigma = Evd.from_ctx ctx in
+ let env = Global.env () and sigma = Evd.from_ctx uctx in
let pr_ltype = pr_ltype_env env sigma in
hov 0 (
match val_0 with
diff --git a/vernac/proof_using.ml b/vernac/proof_using.ml
index 95680c2a4e..bdb0cabacf 100644
--- a/vernac/proof_using.ml
+++ b/vernac/proof_using.ml
@@ -18,30 +18,30 @@ module NamedDecl = Context.Named.Declaration
let known_names = Summary.ref [] ~name:"proofusing-nameset"
-let rec close_fwd e s =
+let rec close_fwd env sigma s =
let s' =
List.fold_left (fun s decl ->
let vb = match decl with
| LocalAssum _ -> Id.Set.empty
- | LocalDef (_,b,_) -> global_vars_set e b
+ | LocalDef (_,b,_) -> Termops.global_vars_set env sigma b
in
- let vty = global_vars_set e (NamedDecl.get_type decl) in
+ let vty = Termops.global_vars_set env sigma (NamedDecl.get_type decl) in
let vbty = Id.Set.union vb vty in
if Id.Set.exists (fun v -> Id.Set.mem v s) vbty
then Id.Set.add (NamedDecl.get_id decl) (Id.Set.union s vbty) else s)
- s (named_context e)
+ s (EConstr.named_context env)
in
- if Id.Set.equal s s' then s else close_fwd e s'
+ if Id.Set.equal s s' then s else close_fwd env sigma s'
-let set_of_type env ty =
+let set_of_type env sigma ty =
List.fold_left (fun acc ty ->
- Id.Set.union (global_vars_set env ty) acc)
+ Id.Set.union (Termops.global_vars_set env sigma ty) acc)
Id.Set.empty ty
let full_set env =
List.fold_right Id.Set.add (List.map NamedDecl.get_id (named_context env)) Id.Set.empty
-let process_expr env e v_ty =
+let process_expr env sigma e v_ty =
let rec aux = function
| SsEmpty -> Id.Set.empty
| SsType -> v_ty
@@ -49,7 +49,7 @@ let process_expr env e v_ty =
| SsUnion(e1,e2) -> Id.Set.union (aux e1) (aux e2)
| SsSubstr(e1,e2) -> Id.Set.diff (aux e1) (aux e2)
| SsCompl e -> Id.Set.diff (full_set env) (aux e)
- | SsFwdClose e -> close_fwd env (aux e)
+ | SsFwdClose e -> close_fwd env sigma (aux e)
and set_of_id id =
if Id.to_string id = "All" then
full_set env
@@ -59,9 +59,9 @@ let process_expr env e v_ty =
in
aux e
-let process_expr env e ty =
- let v_ty = set_of_type env ty in
- let s = Id.Set.union v_ty (process_expr env e v_ty) in
+let process_expr env sigma e ty =
+ let v_ty = set_of_type env sigma ty in
+ let s = Id.Set.union v_ty (process_expr env sigma e v_ty) in
Id.Set.elements s
let name_set id expr = known_names := (id,expr) :: !known_names
@@ -110,7 +110,7 @@ let suggest_common env ppid used ids_typ skip =
S.empty (named_context env)
in
let all = S.diff all skip in
- let fwd_typ = close_fwd env ids_typ in
+ let fwd_typ = close_fwd env (Evd.from_env env) ids_typ in
if !Flags.debug then begin
print (str "All " ++ pr_set false all);
print (str "Type " ++ pr_set false ids_typ);
diff --git a/vernac/proof_using.mli b/vernac/proof_using.mli
index dfc233e8fa..93dbd33ae4 100644
--- a/vernac/proof_using.mli
+++ b/vernac/proof_using.mli
@@ -11,7 +11,8 @@
(** Utility code for section variables handling in Proof using... *)
val process_expr :
- Environ.env -> Vernacexpr.section_subset_expr -> Constr.types list ->
+ Environ.env -> Evd.evar_map ->
+ Vernacexpr.section_subset_expr -> EConstr.types list ->
Names.Id.t list
val name_set : Names.Id.t -> Vernacexpr.section_subset_expr -> unit
@@ -24,3 +25,5 @@ val get_default_proof_using : unit -> Vernacexpr.section_subset_expr option
val proof_using_opt_name : string list
(** For the stm *)
+
+val using_from_string : string -> Vernacexpr.section_subset_expr
diff --git a/vernac/record.ml b/vernac/record.ml
index acc97f61c1..2c56604d8f 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -124,7 +124,7 @@ let typecheck_params_and_fields def poly pl ps records =
let is_template =
List.exists (fun (_, arity, _, _) -> Option.cata check_anonymous_type true arity) records in
let env0 = if not poly && is_template then Environ.set_universes_lbound env0 UGraph.Bound.Prop else env0 in
- let sigma, decl = Constrexpr_ops.interp_univ_decl_opt env0 pl in
+ let sigma, decl = interp_univ_decl_opt env0 pl in
let () =
let error bk {CAst.loc; v=name} =
match bk, name with
diff --git a/vernac/search.ml b/vernac/search.ml
index abefeab779..501e5b1a91 100644
--- a/vernac/search.ml
+++ b/vernac/search.ml
@@ -216,18 +216,16 @@ let name_of_reference ref = Id.to_string (Nametab.basename_of_global ref)
let search_filter query gr kind env sigma typ = match query with
| GlobSearchSubPattern (where,head,pat) ->
let open Context.Rel.Declaration in
- let collect_hyps ctx =
- List.fold_left (fun acc d -> match get_value d with
- | None -> get_type d :: acc
- | Some b -> b :: get_type d :: acc) [] ctx in
+ let rec collect env hyps typ =
+ match Constr.kind typ with
+ | LetIn (na,b,t,c) -> collect (push_rel (LocalDef (na,b,t)) env) ((env,b) :: (env,t) :: hyps) c
+ | Prod (na,t,c) -> collect (push_rel (LocalAssum (na,t)) env) ((env,t) :: hyps) c
+ | _ -> (hyps,(env,typ)) in
let typl= match where with
- | InHyp -> collect_hyps (fst (Term.decompose_prod_assum typ))
- | InConcl -> [snd (Term.decompose_prod_assum typ)]
- | Anywhere ->
- if head then
- let ctx, ccl = Term.decompose_prod_assum typ in ccl :: collect_hyps ctx
- else [typ] in
- List.exists (fun typ ->
+ | InHyp -> fst (collect env [] typ)
+ | InConcl -> [snd (collect env [] typ)]
+ | Anywhere -> if head then let hyps, ccl = collect env [] typ in ccl :: hyps else [env,typ] in
+ List.exists (fun (env,typ) ->
let f =
if head then Constr_matching.is_matching_head
else Constr_matching.is_matching_appsubterm ~closed:false in
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 3ced38d6ea..824bf35b1d 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -57,14 +57,16 @@ module DefAttributes = struct
program : bool;
deprecated : Deprecation.t option;
canonical_instance : bool;
+ using : Vernacexpr.section_subset_expr option;
}
let parse f =
let open Attributes in
- let (((locality, deprecated), polymorphic), program), canonical_instance =
- parse Notations.(locality ++ deprecation ++ polymorphic ++ program ++ canonical_instance) f
+ let ((((locality, deprecated), polymorphic), program), canonical_instance), using =
+ parse Notations.(locality ++ deprecation ++ polymorphic ++ program ++ canonical_instance ++ using) f
in
- { polymorphic; program; locality; deprecated; canonical_instance }
+ let using = Option.map Proof_using.using_from_string using in
+ { polymorphic; program; locality; deprecated; canonical_instance; using }
end
let module_locality = Attributes.Notations.(locality >>= fun l -> return (make_module_locality l))
@@ -496,6 +498,25 @@ let program_inference_hook env sigma ev =
user_err Pp.(str "The statement obligations could not be resolved \
automatically, write a statement definition first.")
+let vernac_set_used_variables ~pstate e : Declare.Proof.t =
+ let env = Global.env () in
+ let sigma, _ = Declare.Proof.get_current_context pstate in
+ let initial_goals pf = Proofview.initial_goals Proof.((data pf).entry) in
+ let tys = List.map snd (initial_goals (Declare.Proof.get pstate)) in
+ let l = Proof_using.process_expr env sigma e tys in
+ let vars = Environ.named_context env in
+ List.iter (fun id ->
+ if not (List.exists (NamedDecl.get_id %> Id.equal id) vars) then
+ user_err ~hdr:"vernac_set_used_variables"
+ (str "Unknown variable: " ++ Id.print id))
+ l;
+ let _, pstate = Declare.Proof.set_used_variables pstate l in
+ pstate
+let vernac_set_used_variables_opt ?using pstate =
+ match using with
+ | None -> pstate
+ | Some expr -> vernac_set_used_variables ~pstate expr
+
(* XXX: Interpretation of lemma command, duplication with ComFixpoint
/ ComDefinition ? *)
let interp_lemma ~program_mode ~flags ~scope env0 evd thms =
@@ -525,25 +546,28 @@ let post_check_evd ~udecl ~poly evd =
else (* We fix the variables to ensure they won't be lowered to Set *)
Evd.fix_undefined_variables evd
-let start_lemma_com ~program_mode ~poly ~scope ~kind ?hook thms =
+let start_lemma_com ~program_mode ~poly ~scope ~kind ?using ?hook thms =
let env0 = Global.env () in
let flags = Pretyping.{ all_no_fail_flags with program_mode } in
let decl = fst (List.hd thms) in
- let evd, udecl = Constrexpr_ops.interp_univ_decl_opt env0 (snd decl) in
+ let evd, udecl = Constrintern.interp_univ_decl_opt env0 (snd decl) in
let evd, thms = interp_lemma ~program_mode ~flags ~scope env0 evd thms in
let mut_analysis = RecLemmas.look_for_possibly_mutual_statements evd thms in
let evd = Evd.minimize_universes evd in
- match mut_analysis with
- | RecLemmas.NonMutual thm ->
- let thm = Declare.CInfo.to_constr evd thm in
- let evd = post_check_evd ~udecl ~poly evd in
- let info = Declare.Info.make ?hook ~poly ~scope ~kind ~udecl () in
- Declare.Proof.start_with_initialization ~info ~cinfo:thm evd
- | RecLemmas.Mutual { mutual_info; cinfo ; possible_guards } ->
- let cinfo = List.map (Declare.CInfo.to_constr evd) cinfo in
- let evd = post_check_evd ~udecl ~poly evd in
- let info = Declare.Info.make ?hook ~poly ~scope ~kind ~udecl () in
- Declare.Proof.start_mutual_with_initialization ~info ~cinfo evd ~mutual_info (Some possible_guards)
+ let pstate =
+ match mut_analysis with
+ | RecLemmas.NonMutual thm ->
+ let thm = Declare.CInfo.to_constr evd thm in
+ let evd = post_check_evd ~udecl ~poly evd in
+ let info = Declare.Info.make ?hook ~poly ~scope ~kind ~udecl () in
+ Declare.Proof.start_with_initialization ~info ~cinfo:thm evd
+ | RecLemmas.Mutual { mutual_info; cinfo ; possible_guards } ->
+ let cinfo = List.map (Declare.CInfo.to_constr evd) cinfo in
+ let evd = post_check_evd ~udecl ~poly evd in
+ let info = Declare.Info.make ?hook ~poly ~scope ~kind ~udecl () in
+ Declare.Proof.start_mutual_with_initialization ~info ~cinfo evd ~mutual_info (Some possible_guards)
+ in
+ vernac_set_used_variables_opt ?using pstate
let vernac_definition_hook ~canonical_instance ~local ~poly = let open Decls in function
| Coercion ->
@@ -583,7 +607,7 @@ let vernac_definition_interactive ~atts (discharge, kind) (lid, pl) bl t =
let program_mode = atts.program in
let poly = atts.polymorphic in
let name = vernac_definition_name lid local in
- start_lemma_com ~program_mode ~poly ~scope:local ~kind:(Decls.IsDefinition kind) ?hook [(name, pl), (bl, t)]
+ start_lemma_com ~program_mode ~poly ~scope:local ~kind:(Decls.IsDefinition kind) ?using:atts.using ?hook [(name, pl), (bl, t)]
let vernac_definition ~atts ~pm (discharge, kind) (lid, pl) bl red_option c typ_opt =
let open DefAttributes in
@@ -604,7 +628,7 @@ let vernac_definition ~atts ~pm (discharge, kind) (lid, pl) bl red_option c typ_
else
let () =
ComDefinition.do_definition ~name:name.v
- ~poly:atts.polymorphic ~scope ~kind pl bl red_option c typ_opt ?hook in
+ ~poly:atts.polymorphic ~scope ~kind ?using:atts.using pl bl red_option c typ_opt ?hook in
pm
(* NB: pstate argument to use combinators easily *)
@@ -613,7 +637,7 @@ let vernac_start_proof ~atts kind l =
let scope = enforce_locality_exp atts.locality NoDischarge in
if Dumpglob.dump () then
List.iter (fun ((id, _), _) -> Dumpglob.dump_definition id false "prf") l;
- start_lemma_com ~program_mode:atts.program ~poly:atts.polymorphic ~scope ~kind:(Decls.IsProof kind) l
+ start_lemma_com ~program_mode:atts.program ~poly:atts.polymorphic ~scope ~kind:(Decls.IsProof kind) ?using:atts.using l
let vernac_end_proof ~lemma ~pm = let open Vernacexpr in function
| Admitted ->
@@ -639,6 +663,8 @@ let vernac_assumption ~atts discharge kind l nl =
match scope with
| Global _ -> Dumpglob.dump_definition lid false "ax"
| Discharge -> Dumpglob.dump_definition lid true "var") idl) l;
+ if Option.has_some atts.using then
+ Attributes.unsupported_attributes ["using",VernacFlagEmpty];
ComAssumption.do_assumptions ~poly:atts.polymorphic ~program_mode:atts.program ~scope ~kind nl l
let is_polymorphic_inductive_cumulativity =
@@ -842,16 +868,17 @@ let vernac_fixpoint_interactive ~atts discharge l =
let scope = vernac_fixpoint_common ~atts discharge l in
if atts.program then
CErrors.user_err Pp.(str"Program Fixpoint requires a body");
- ComFixpoint.do_fixpoint_interactive ~scope ~poly:atts.polymorphic l
+ vernac_set_used_variables_opt ?using:atts.using
+ (ComFixpoint.do_fixpoint_interactive ~scope ~poly:atts.polymorphic l)
let vernac_fixpoint ~atts ~pm discharge l =
let open DefAttributes in
let scope = vernac_fixpoint_common ~atts discharge l in
if atts.program then
(* XXX: Switch to the attribute system and match on ~atts *)
- ComProgramFixpoint.do_fixpoint ~pm ~scope ~poly:atts.polymorphic l
+ ComProgramFixpoint.do_fixpoint ~pm ~scope ~poly:atts.polymorphic ?using:atts.using l
else
- let () = ComFixpoint.do_fixpoint ~scope ~poly:atts.polymorphic l in
+ let () = ComFixpoint.do_fixpoint ~scope ~poly:atts.polymorphic ?using:atts.using l in
pm
let vernac_cofixpoint_common ~atts discharge l =
@@ -864,15 +891,16 @@ let vernac_cofixpoint_interactive ~atts discharge l =
let scope = vernac_cofixpoint_common ~atts discharge l in
if atts.program then
CErrors.user_err Pp.(str"Program CoFixpoint requires a body");
- ComFixpoint.do_cofixpoint_interactive ~scope ~poly:atts.polymorphic l
+ vernac_set_used_variables_opt ?using:atts.using
+ (ComFixpoint.do_cofixpoint_interactive ~scope ~poly:atts.polymorphic l)
let vernac_cofixpoint ~atts ~pm discharge l =
let open DefAttributes in
let scope = vernac_cofixpoint_common ~atts discharge l in
if atts.program then
- ComProgramFixpoint.do_cofixpoint ~pm ~scope ~poly:atts.polymorphic l
+ ComProgramFixpoint.do_cofixpoint ~pm ~scope ~poly:atts.polymorphic ?using:atts.using l
else
- let () = ComFixpoint.do_cofixpoint ~scope ~poly:atts.polymorphic l in
+ let () = ComFixpoint.do_cofixpoint ~scope ~poly:atts.polymorphic ?using:atts.using l in
pm
let vernac_scheme l =
@@ -957,9 +985,15 @@ let interp_filter_in m = function
let vernac_import export refl =
let import_mod (qid,f) =
- let m = try Nametab.locate_module qid
+ let loc = qid.loc in
+ let m = try
+ let m = Nametab.locate_module qid in
+ let () = if Modops.is_functor (Global.lookup_module m).Declarations.mod_type
+ then CErrors.user_err ?loc Pp.(str "Cannot import functor " ++ pr_qualid qid ++ str".")
+ in
+ m
with Not_found ->
- CErrors.user_err Pp.(str "Cannot find module " ++ pr_qualid qid)
+ CErrors.user_err ?loc Pp.(str "Cannot find module " ++ pr_qualid qid)
in
let f = interp_filter_in m f in
Declaremods.import_module f ~export m
@@ -1223,21 +1257,6 @@ let vernac_set_end_tac ~pstate tac =
(* TO DO verifier s'il faut pas mettre exist s | TacId s ici*)
Declare.Proof.set_endline_tactic tac pstate
-let vernac_set_used_variables ~pstate e : Declare.Proof.t =
- let env = Global.env () in
- let initial_goals pf = Proofview.initial_goals Proof.(data pf).Proof.entry in
- let tys = List.map snd (initial_goals (Declare.Proof.get pstate)) in
- let tys = List.map EConstr.Unsafe.to_constr tys in
- let l = Proof_using.process_expr env e tys in
- let vars = Environ.named_context env in
- List.iter (fun id ->
- if not (List.exists (NamedDecl.get_id %> Id.equal id) vars) then
- user_err ~hdr:"vernac_set_used_variables"
- (str "Unknown variable: " ++ Id.print id))
- l;
- let _, pstate = Declare.Proof.set_used_variables pstate l in
- pstate
-
(*****************************)
(* Auxiliary file management *)