aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/CODEOWNERS2
-rw-r--r--.github/ISSUE_TEMPLATE.md21
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml41
-rw-r--r--.travis.yml116
-rw-r--r--CHANGES.md47
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--INSTALL14
-rw-r--r--META.coq.in32
-rw-r--r--Makefile5
-rw-r--r--Makefile.build30
-rw-r--r--Makefile.common3
-rw-r--r--Makefile.dune2
-rw-r--r--README.md8
-rw-r--r--appveyor.yml22
-rw-r--r--checker/analyze.ml39
-rw-r--r--checker/analyze.mli2
-rw-r--r--checker/checkInductive.ml5
-rw-r--r--checker/mod_checking.ml1
-rw-r--r--checker/safe_checking.ml1
-rw-r--r--checker/validate.ml5
-rw-r--r--checker/values.ml25
-rw-r--r--checker/values.mli2
-rw-r--r--checker/votour.ml4
-rw-r--r--configure.ml2
-rw-r--r--default.nix6
-rwxr-xr-xdev/build/windows/makecoq_mingw.sh3
-rw-r--r--dev/ci/README-developers.md9
-rw-r--r--dev/ci/appveyor.bat42
-rwxr-xr-xdev/ci/ci-basic-overlay.sh2
-rwxr-xr-xdev/ci/ci-wrapper.sh10
-rw-r--r--dev/ci/docker/bionic_coq/Dockerfile4
-rw-r--r--dev/ci/nix/CoLoR.nix2
-rw-r--r--dev/ci/nix/Corn.nix2
-rw-r--r--dev/ci/nix/GeoCoq.nix2
-rw-r--r--dev/ci/nix/README.md7
-rw-r--r--dev/ci/nix/default.nix30
-rw-r--r--dev/ci/nix/fiat_crypto.nix2
-rw-r--r--dev/ci/nix/formal-topology.nix4
-rw-r--r--dev/ci/nix/math_classes.nix2
-rw-r--r--dev/ci/nix/mtac2.nix3
-rw-r--r--dev/ci/nix/oddorder.nix2
-rw-r--r--dev/ci/nix/quickchick.nix5
-rwxr-xr-xdev/ci/nix/shell8
-rw-r--r--dev/ci/nix/unicoq/META2
-rw-r--r--dev/ci/nix/unicoq/default.nix (renamed from dev/ci/nix/unicoq.nix)8
-rw-r--r--dev/ci/nix/unicoq/unicoq-num.patch44
-rw-r--r--dev/ci/user-overlays/06914-maximedenes-primitive-integers.sh9
-rw-r--r--dev/ci/user-overlays/09263-maximedenes-parsing-state.sh12
-rw-r--r--dev/doc/MERGING.md2
-rw-r--r--dev/doc/profiling.txt6
-rw-r--r--dev/doc/release-process.md58
-rw-r--r--dev/doc/versions-history.tex2
-rwxr-xr-xdev/tools/merge-pr.sh2
-rwxr-xr-xdev/tools/update-compat.py245
-rw-r--r--dev/top_printers.ml4
-rw-r--r--dev/vm_printers.ml1
-rw-r--r--doc/common/macros.tex10
-rw-r--r--doc/sphinx/README.rst4
-rw-r--r--doc/sphinx/README.template.rst4
-rw-r--r--doc/sphinx/addendum/generalized-rewriting.rst72
-rw-r--r--doc/sphinx/addendum/implicit-coercions.rst14
-rw-r--r--doc/sphinx/addendum/micromega.rst14
-rw-r--r--doc/sphinx/addendum/parallel-proof-processing.rst54
-rw-r--r--doc/sphinx/addendum/ring.rst14
-rw-r--r--doc/sphinx/language/cic.rst376
-rw-r--r--doc/sphinx/language/coq-library.rst38
-rw-r--r--doc/sphinx/language/gallina-extensions.rst25
-rw-r--r--doc/sphinx/language/gallina-specification-language.rst106
-rw-r--r--doc/sphinx/practical-tools/coq-commands.rst16
-rw-r--r--doc/sphinx/proof-engine/ltac.rst170
-rw-r--r--doc/sphinx/proof-engine/ssreflect-proof-language.rst77
-rw-r--r--doc/sphinx/proof-engine/tactics.rst724
-rw-r--r--doc/sphinx/refman-preamble.sty10
-rw-r--r--doc/sphinx/user-extensions/syntax-extensions.rst77
-rw-r--r--doc/stdlib/index-list.html.template10
-rw-r--r--dune6
-rw-r--r--engine/eConstr.ml4
-rw-r--r--engine/eConstr.mli2
-rw-r--r--engine/namegen.ml3
-rw-r--r--engine/proofview.ml2
-rw-r--r--engine/termops.ml8
-rw-r--r--engine/termops.mli2
-rw-r--r--engine/uState.ml226
-rw-r--r--ide/fake_ide.ml7
-rw-r--r--ide/idetop.ml34
-rw-r--r--interp/constrextern.ml12
-rw-r--r--interp/declare.ml3
-rw-r--r--interp/declare.mli1
-rw-r--r--interp/dumpglob.ml1
-rw-r--r--interp/impargs.ml2
-rw-r--r--interp/notation.ml41
-rw-r--r--interp/notation.mli4
-rw-r--r--interp/notation_ops.ml10
-rw-r--r--interp/notation_term.ml1
-rw-r--r--kernel/byterun/coq_fix_code.c25
-rw-r--r--kernel/byterun/coq_fix_code.h1
-rw-r--r--kernel/byterun/coq_instruct.h26
-rw-r--r--kernel/byterun/coq_interp.c578
-rw-r--r--kernel/byterun/coq_uint63_emul.h97
-rw-r--r--kernel/byterun/coq_uint63_native.h125
-rw-r--r--kernel/byterun/coq_values.h12
-rw-r--r--kernel/byterun/dune4
-rw-r--r--kernel/cClosure.ml348
-rw-r--r--kernel/cClosure.mli11
-rw-r--r--kernel/cPrimitives.ml218
-rw-r--r--kernel/cPrimitives.mli81
-rw-r--r--kernel/cbytecodes.ml114
-rw-r--r--kernel/cbytecodes.mli74
-rw-r--r--kernel/cbytegen.ml183
-rw-r--r--kernel/cbytegen.mli3
-rw-r--r--kernel/cemitcodes.ml82
-rw-r--r--kernel/cemitcodes.mli7
-rw-r--r--kernel/cinstr.mli52
-rw-r--r--kernel/clambda.ml305
-rw-r--r--kernel/clambda.mli49
-rw-r--r--kernel/constr.ml45
-rw-r--r--kernel/constr.mli4
-rw-r--r--kernel/context.ml9
-rw-r--r--kernel/context.mli3
-rw-r--r--kernel/cooking.ml3
-rw-r--r--kernel/cooking.mli2
-rw-r--r--kernel/declarations.ml7
-rw-r--r--kernel/declareops.ml8
-rw-r--r--kernel/dune16
-rw-r--r--kernel/entries.ml7
-rw-r--r--kernel/environ.ml51
-rw-r--r--kernel/environ.mli27
-rw-r--r--kernel/indtypes.ml10
-rw-r--r--kernel/inductive.ml7
-rw-r--r--kernel/kernel.mllib5
-rw-r--r--kernel/mod_subst.ml13
-rw-r--r--kernel/mod_subst.mli2
-rw-r--r--kernel/mod_typing.ml78
-rw-r--r--kernel/modops.ml49
-rw-r--r--kernel/modops.mli2
-rw-r--r--kernel/nativecode.ml198
-rw-r--r--kernel/nativeconv.ml4
-rw-r--r--kernel/nativeinstr.mli59
-rw-r--r--kernel/nativelambda.ml183
-rw-r--r--kernel/nativelambda.mli51
-rw-r--r--kernel/nativevalues.ml210
-rw-r--r--kernel/nativevalues.mli67
-rw-r--r--kernel/primred.ml208
-rw-r--r--kernel/primred.mli44
-rw-r--r--kernel/reduction.ml177
-rw-r--r--kernel/retroknowledge.ml259
-rw-r--r--kernel/retroknowledge.mli163
-rw-r--r--kernel/safe_typing.ml225
-rw-r--r--kernel/safe_typing.mli6
-rw-r--r--kernel/subtyping.ml4
-rw-r--r--kernel/term.ml2
-rw-r--r--kernel/term_typing.ml42
-rw-r--r--kernel/typeops.ml90
-rw-r--r--kernel/typeops.mli10
-rw-r--r--kernel/uint31.ml153
-rw-r--r--kernel/uint63.mli (renamed from kernel/uint31.mli)30
-rw-r--r--kernel/uint63_amd64.ml215
-rw-r--r--kernel/uint63_x86.ml209
-rw-r--r--kernel/vconv.ml20
-rw-r--r--kernel/vm.ml3
-rw-r--r--kernel/vmvalues.ml22
-rw-r--r--kernel/vmvalues.mli3
-rw-r--r--kernel/write_uint63.ml30
-rw-r--r--lib/flags.ml6
-rw-r--r--lib/flags.mli2
-rw-r--r--lib/stateid.ml2
-rw-r--r--lib/stateid.mli1
-rw-r--r--library/decl_kinds.ml1
-rw-r--r--library/global.ml5
-rw-r--r--library/global.mli4
-rw-r--r--library/keys.ml6
-rw-r--r--man/coqtop.118
-rw-r--r--parsing/pcoq.ml1
-rw-r--r--parsing/pcoq.mli14
-rw-r--r--plugins/derive/g_derive.mlg2
-rw-r--r--plugins/extraction/extract_env.ml2
-rw-r--r--plugins/extraction/extraction.ml19
-rw-r--r--plugins/extraction/haskell.ml2
-rw-r--r--plugins/extraction/json.ml4
-rw-r--r--plugins/extraction/miniml.ml1
-rw-r--r--plugins/extraction/miniml.mli1
-rw-r--r--plugins/extraction/mlutil.ml29
-rw-r--r--plugins/extraction/modutil.ml2
-rw-r--r--plugins/extraction/ocaml.ml4
-rw-r--r--plugins/extraction/scheme.ml2
-rw-r--r--plugins/funind/functional_principles_proofs.ml3
-rw-r--r--plugins/funind/g_indfun.mlg2
-rw-r--r--plugins/funind/glob_term_to_relation.ml5
-rw-r--r--plugins/funind/glob_termops.ml6
-rw-r--r--plugins/funind/indfun.ml2
-rw-r--r--plugins/funind/recdef.ml4
-rw-r--r--plugins/ltac/g_ltac.mlg11
-rw-r--r--plugins/ltac/g_obligations.mlg2
-rw-r--r--plugins/ltac/g_rewrite.mlg4
-rw-r--r--plugins/ltac/g_tactic.mlg8
-rw-r--r--plugins/micromega/coq_micromega.ml2
-rw-r--r--plugins/nsatz/Nsatz.v3
-rw-r--r--plugins/omega/PreOmega.v132
-rw-r--r--plugins/setoid_ring/Ncring_initial.v1
-rw-r--r--plugins/setoid_ring/Ncring_tac.v18
-rw-r--r--plugins/setoid_ring/Rings_Q.v1
-rw-r--r--plugins/setoid_ring/Rings_R.v1
-rw-r--r--plugins/ssr/ssrast.mli14
-rw-r--r--plugins/ssr/ssrcommon.ml2
-rw-r--r--plugins/ssr/ssrcommon.mli2
-rw-r--r--plugins/ssr/ssrfwd.ml26
-rw-r--r--plugins/ssr/ssrfwd.mli6
-rw-r--r--plugins/ssr/ssripats.ml251
-rw-r--r--plugins/ssr/ssripats.mli38
-rw-r--r--plugins/ssr/ssrparser.mlg54
-rw-r--r--plugins/ssr/ssrprinters.ml10
-rw-r--r--plugins/ssr/ssrprinters.mli1
-rw-r--r--plugins/ssr/ssrview.ml9
-rw-r--r--plugins/ssrmatching/ssrmatching.ml3
-rw-r--r--plugins/syntax/int31_syntax.ml114
-rw-r--r--plugins/syntax/int31_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/int63_syntax.ml55
-rw-r--r--plugins/syntax/int63_syntax_plugin.mlpack1
-rw-r--r--plugins/syntax/numeral.ml117
-rw-r--r--plugins/syntax/plugin_base.dune8
-rw-r--r--pretyping/arguments_renaming.ml2
-rw-r--r--pretyping/cbv.ml167
-rw-r--r--pretyping/cbv.mli1
-rw-r--r--pretyping/constr_matching.ml5
-rw-r--r--pretyping/detyping.ml4
-rw-r--r--pretyping/evarconv.ml15
-rw-r--r--pretyping/glob_ops.ml11
-rw-r--r--pretyping/glob_term.ml1
-rw-r--r--pretyping/heads.ml1
-rw-r--r--pretyping/inferCumulativity.ml5
-rw-r--r--pretyping/nativenorm.ml12
-rw-r--r--pretyping/pattern.ml1
-rw-r--r--pretyping/patternops.ml20
-rw-r--r--pretyping/pretype_errors.ml4
-rw-r--r--pretyping/pretype_errors.mli3
-rw-r--r--pretyping/pretyping.ml11
-rw-r--r--pretyping/reductionops.ml213
-rw-r--r--pretyping/reductionops.mli1
-rw-r--r--pretyping/retyping.ml1
-rw-r--r--pretyping/tacred.ml4
-rw-r--r--pretyping/typing.ml6
-rw-r--r--pretyping/typing.mli1
-rw-r--r--pretyping/unification.ml8
-rw-r--r--pretyping/vnorm.ml28
-rw-r--r--printing/prettyp.ml11
-rw-r--r--printing/proof_diffs.ml2
-rw-r--r--proofs/goal_select.ml2
-rw-r--r--proofs/proof_global.ml92
-rw-r--r--proofs/proof_global.mli45
-rw-r--r--stm/asyncTaskQueue.ml28
-rw-r--r--stm/stm.ml485
-rw-r--r--stm/stm.mli13
-rw-r--r--stm/vernac_classifier.ml30
-rw-r--r--tactics/tactics.ml2
-rw-r--r--tactics/term_dnet.ml25
-rw-r--r--test-suite/Makefile50
-rw-r--r--test-suite/arithmetic/add.v18
-rw-r--r--test-suite/arithmetic/addc.v17
-rw-r--r--test-suite/arithmetic/addcarryc.v17
-rw-r--r--test-suite/arithmetic/addmuldiv.v12
-rw-r--r--test-suite/arithmetic/compare.v23
-rw-r--r--test-suite/arithmetic/div.v17
-rw-r--r--test-suite/arithmetic/diveucl.v17
-rw-r--r--test-suite/arithmetic/diveucl_21.v17
-rw-r--r--test-suite/arithmetic/eqb.v17
-rw-r--r--test-suite/arithmetic/head0.v23
-rw-r--r--test-suite/arithmetic/isint.v50
-rw-r--r--test-suite/arithmetic/land.v29
-rw-r--r--test-suite/arithmetic/leb.v23
-rw-r--r--test-suite/arithmetic/lor.v29
-rw-r--r--test-suite/arithmetic/lsl.v23
-rw-r--r--test-suite/arithmetic/lsr.v23
-rw-r--r--test-suite/arithmetic/ltb.v23
-rw-r--r--test-suite/arithmetic/lxor.v29
-rw-r--r--test-suite/arithmetic/mod.v17
-rw-r--r--test-suite/arithmetic/mul.v17
-rw-r--r--test-suite/arithmetic/mulc.v22
-rw-r--r--test-suite/arithmetic/primitive.v12
-rw-r--r--test-suite/arithmetic/reduction.v28
-rw-r--r--test-suite/arithmetic/sub.v17
-rw-r--r--test-suite/arithmetic/subc.v17
-rw-r--r--test-suite/arithmetic/subcarryc.v17
-rw-r--r--test-suite/arithmetic/tail0.v23
-rw-r--r--test-suite/arithmetic/unsigned.v18
-rw-r--r--test-suite/bugs/closed/HoTT_coq_056.v4
-rw-r--r--test-suite/bugs/closed/bug_3324.v4
-rw-r--r--test-suite/bugs/closed/bug_3454.v6
-rw-r--r--test-suite/bugs/closed/bug_3682.v2
-rw-r--r--test-suite/bugs/closed/bug_4782.v4
-rw-r--r--test-suite/bugs/closed/bug_4798.v2
-rw-r--r--test-suite/bugs/closed/bug_4836.v2
-rw-r--r--test-suite/bugs/closed/bug_5401.v2
-rw-r--r--test-suite/bugs/closed/bug_7811.v2
-rw-r--r--test-suite/bugs/closed/bug_8076.v3
-rw-r--r--test-suite/bugs/closed/bug_9166.v2
-rw-r--r--test-suite/bugs/closed/bug_9268.v46
-rw-r--r--test-suite/bugs/closed/bug_9367.v12
-rw-r--r--test-suite/bugs/closed/bug_9451.v8
-rw-r--r--test-suite/bugs/closed/bug_9453.v7
-rw-r--r--test-suite/complexity/constructor.v1
-rw-r--r--test-suite/complexity/f_equal.v1
-rw-r--r--test-suite/complexity/injection.v1
-rw-r--r--test-suite/complexity/ring.v1
-rw-r--r--test-suite/complexity/ring2.v1
-rw-r--r--test-suite/complexity/setoid_rewrite.v1
-rw-r--r--test-suite/complexity/unification.v1
-rw-r--r--test-suite/coqchk/inductive_functor_squash.v15
-rw-r--r--test-suite/failure/int63.v (renamed from test-suite/failure/int31.v)7
-rw-r--r--test-suite/ide/debug_ltac.fake2
-rwxr-xr-xtest-suite/misc/4722.sh6
-rwxr-xr-xtest-suite/misc/7704.sh2
-rw-r--r--test-suite/misc/aux7704.v1
-rwxr-xr-xtest-suite/misc/deps-checksum.sh2
-rwxr-xr-xtest-suite/misc/deps-order.sh6
-rwxr-xr-xtest-suite/misc/deps-utf8.sh2
-rwxr-xr-xtest-suite/misc/exitstatus.sh5
-rw-r--r--test-suite/misc/universes/dune2
-rw-r--r--test-suite/output/Arguments_renaming.out2
-rw-r--r--test-suite/output/Binder.out4
-rw-r--r--test-suite/output/Cases.out13
-rw-r--r--test-suite/output/FunExt.v1
-rw-r--r--test-suite/output/Implicit.out1
-rw-r--r--test-suite/output/Int31Syntax.out2
-rw-r--r--test-suite/output/Int31Syntax.v3
-rw-r--r--test-suite/output/Int63Syntax.out16
-rw-r--r--test-suite/output/Int63Syntax.v12
-rw-r--r--test-suite/output/Load.out4
-rw-r--r--test-suite/output/Notations3.out5
-rw-r--r--test-suite/output/Notations4.out8
-rw-r--r--test-suite/output/Notations4.v29
-rw-r--r--test-suite/output/PatternsInBinders.out12
-rw-r--r--test-suite/output/PrintInfos.out2
-rw-r--r--test-suite/output/RecognizePluginWarning.v2
-rw-r--r--test-suite/output/Show.v2
-rw-r--r--test-suite/output/StringSyntax.out3
-rw-r--r--test-suite/output/TranspModtype.out8
-rw-r--r--test-suite/output/UnclosedBlocks.v1
-rw-r--r--test-suite/output/UnivBinders.out34
-rw-r--r--test-suite/output/UsePluginWarning.v3
-rw-r--r--test-suite/output/goal_output.out4
-rw-r--r--test-suite/output/inference.out2
-rw-r--r--test-suite/output/simpl.v1
-rw-r--r--test-suite/output/sint63Notation.out24
-rw-r--r--test-suite/output/sint63Notation.v37
-rw-r--r--test-suite/output/unifconstraints.v1
-rwxr-xr-xtest-suite/report.sh16
-rw-r--r--test-suite/ssr/ipat_replace.v17
-rw-r--r--test-suite/success/Compat88.v4
-rw-r--r--test-suite/success/CompatCurrentFlag.v4
-rw-r--r--test-suite/success/CompatOldFlag.v4
-rw-r--r--test-suite/success/CompatOldOldFlag.v6
-rw-r--r--test-suite/success/CompatPreviousFlag.v4
-rw-r--r--test-suite/success/Nia.v918
-rw-r--r--test-suite/success/NumeralNotations.v11
-rw-r--r--test-suite/success/Typeclasses.v12
-rw-r--r--test-suite/success/auto.v10
-rw-r--r--test-suite/success/bteauto.v8
-rw-r--r--test-suite/success/destruct.v2
-rw-r--r--test-suite/success/eauto.v12
-rw-r--r--test-suite/success/setoid_test2.v4
-rwxr-xr-xtest-suite/tools/update-compat/run.sh2
-rw-r--r--theories/Bool/BoolEq.v4
-rw-r--r--theories/Bool/IfProp.v4
-rw-r--r--theories/Classes/CMorphisms.v63
-rw-r--r--theories/Classes/CRelationClasses.v22
-rw-r--r--theories/Classes/Morphisms.v79
-rw-r--r--theories/Classes/Morphisms_Prop.v10
-rw-r--r--theories/Classes/RelationClasses.v18
-rw-r--r--theories/Classes/RelationPairs.v3
-rw-r--r--theories/Classes/SetoidTactics.v1
-rw-r--r--theories/Compat/Coq810.v11
-rw-r--r--theories/Compat/Coq88.v4
-rw-r--r--theories/Compat/Coq89.v2
-rw-r--r--theories/Init/Decimal.v5
-rw-r--r--theories/Init/Logic.v9
-rw-r--r--theories/Init/Prelude.v2
-rw-r--r--theories/Init/Specif.v5
-rw-r--r--theories/Init/Tactics.v8
-rw-r--r--theories/Lists/StreamMemo.v46
-rw-r--r--theories/Lists/Streams.v60
-rw-r--r--theories/Logic/Berardi.v18
-rw-r--r--theories/Logic/EqdepFacts.v3
-rw-r--r--theories/Logic/Eqdep_dec.v26
-rw-r--r--theories/Logic/JMeq.v8
-rw-r--r--theories/Numbers/BinNums.v1
-rw-r--r--theories/Numbers/Cyclic/Abstract/DoubleType.v6
-rw-r--r--theories/Numbers/Cyclic/Int31/Cyclic31.v6
-rw-r--r--theories/Numbers/Cyclic/Int31/Int31.v35
-rw-r--r--theories/Numbers/Cyclic/Int31/Ring31.v3
-rw-r--r--theories/Numbers/Cyclic/Int63/Cyclic63.v330
-rw-r--r--theories/Numbers/Cyclic/Int63/Int63.v1918
-rw-r--r--theories/Numbers/Cyclic/Int63/Ring63.v65
-rw-r--r--theories/Numbers/NatInt/NZAdd.v25
-rw-r--r--theories/Numbers/NatInt/NZAddOrder.v22
-rw-r--r--theories/Numbers/NatInt/NZBase.v10
-rw-r--r--theories/Numbers/NatInt/NZDiv.v190
-rw-r--r--theories/Numbers/NatInt/NZGcd.v104
-rw-r--r--theories/Numbers/NatInt/NZLog.v601
-rw-r--r--theories/Numbers/NatInt/NZMul.v25
-rw-r--r--theories/Numbers/NatInt/NZMulOrder.v191
-rw-r--r--theories/Numbers/NatInt/NZOrder.v175
-rw-r--r--theories/Numbers/NatInt/NZParity.v64
-rw-r--r--theories/Numbers/NatInt/NZPow.v326
-rw-r--r--theories/Numbers/NatInt/NZSqrt.v493
-rw-r--r--theories/Program/Subset.v6
-rw-r--r--theories/Program/Wf.v20
-rw-r--r--theories/Relations/Operators_Properties.v183
-rw-r--r--theories/Sets/Constructive_sets.v4
-rw-r--r--theories/Sets/Partial_Order.v20
-rw-r--r--theories/Sets/Permut.v32
-rw-r--r--theories/Sets/Powerset.v18
-rw-r--r--theories/Sets/Powerset_facts.v48
-rw-r--r--theories/Sets/Relations_1_facts.v12
-rw-r--r--theories/Sets/Relations_2_facts.v48
-rw-r--r--theories/Sets/Relations_3_facts.v152
-rw-r--r--theories/Sets/Uniset.v12
-rw-r--r--theories/Structures/Equalities.v10
-rw-r--r--theories/Structures/GenericMinMax.v90
-rw-r--r--theories/Structures/Orders.v54
-rw-r--r--theories/Structures/OrdersFacts.v6
-rw-r--r--theories/Wellfounded/Disjoint_Union.v8
-rw-r--r--theories/Wellfounded/Lexicographic_Product.v90
-rw-r--r--theories/Wellfounded/Union.v38
-rw-r--r--theories/Wellfounded/Well_Ordering.v6
-rw-r--r--tools/coq_dune.ml11
-rw-r--r--tools/coqc.ml163
-rw-r--r--tools/dune7
-rw-r--r--topbin/coqc_bin.ml13
-rw-r--r--topbin/dune10
-rw-r--r--toplevel/ccompile.ml43
-rw-r--r--toplevel/ccompile.mli6
-rw-r--r--toplevel/coqargs.ml147
-rw-r--r--toplevel/coqargs.mli31
-rw-r--r--toplevel/coqc.ml67
-rw-r--r--toplevel/coqc.mli11
-rw-r--r--toplevel/coqcargs.ml174
-rw-r--r--toplevel/coqcargs.mli30
-rw-r--r--toplevel/coqloop.ml23
-rw-r--r--toplevel/coqloop.mli4
-rw-r--r--toplevel/coqtop.ml229
-rw-r--r--toplevel/coqtop.mli18
-rw-r--r--toplevel/g_toplevel.mlg18
-rw-r--r--toplevel/toplevel.mllib2
-rw-r--r--toplevel/usage.ml66
-rw-r--r--toplevel/usage.mli3
-rw-r--r--toplevel/vernac.ml74
-rw-r--r--toplevel/workerLoop.ml2
-rw-r--r--vernac/auto_ind_decl.ml1
-rw-r--r--vernac/classes.ml11
-rw-r--r--vernac/comAssumption.ml26
-rw-r--r--vernac/comAssumption.mli2
-rw-r--r--vernac/comInductive.ml16
-rw-r--r--vernac/g_vernac.mlg42
-rw-r--r--vernac/himsg.ml16
-rw-r--r--vernac/lemmas.ml2
-rw-r--r--vernac/obligations.ml8
-rw-r--r--vernac/ppvernac.ml6
-rw-r--r--vernac/pvernac.ml38
-rw-r--r--vernac/pvernac.mli28
-rw-r--r--vernac/record.ml46
-rw-r--r--vernac/topfmt.ml5
-rw-r--r--vernac/topfmt.mli1
-rw-r--r--vernac/vernacentries.ml76
-rw-r--r--vernac/vernacentries.mli5
-rw-r--r--vernac/vernacexpr.ml1
-rw-r--r--vernac/vernacextend.ml6
-rw-r--r--vernac/vernacextend.mli6
-rw-r--r--vernac/vernacstate.ml32
-rw-r--r--vernac/vernacstate.mli17
470 files changed, 13209 insertions, 7161 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 275d6c1ff5..f802040a1d 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -30,8 +30,6 @@
# Trick to avoid getting review requests
# each time someone adds an overlay
-/appveyor.yml @coq/ci-maintainers
-/dev/ci/appveyor.* @coq/ci-maintainers
/dev/ci/*.bat @coq/ci-maintainers
*.nix @coq/nix-maintainers
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index c9cb516cd3..aec6cd0a21 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,18 +1,11 @@
-<!-- Thank you for your contribution.
- Please complete the following information when reporting a bug. -->
+<!-- Thank you for reporting a bug to Coq! -->
-#### Version
-
-<!-- You can get this information by running `coqtop -v`. -->
-
-
-#### Operating system
+#### Description of the problem
+<!-- If you can, it's helpful to provide self-contained example of some code
+that reproduces the bug. If not, a link to a larger example is also helpful. -->
-#### Description of the problem
+#### Coq Version
-<!-- It is helpful to provide enough information so that we can reproduce the bug.
- In particular, please include a code example which produces it.
- If the example is small, you can include it here between ``` ```.
- Otherwise, please provide a link to a repository, a gist (https://gist.github.com)
- or drag-and-drop a `.zip` archive. -->
+<!-- You can get this information by running `coqtop -v`. If relevant, please
+also include your operating system. -->
diff --git a/.gitignore b/.gitignore
index 2e5529ccfb..c30fd850a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -147,6 +147,7 @@ plugins/ssr/ssrvernac.ml
kernel/byterun/coq_jumptbl.h
kernel/copcodes.ml
+kernel/uint63.ml
ide/index_urls.txt
.lia.cache
.nia.cache
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e981c592a2..7ebc2d8a4d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,7 +9,7 @@ stages:
variables:
# Format: $IMAGE-V$DATE [Cache is not used as of today but kept here
# for reference]
- CACHEKEY: "bionic_coq-V2018-12-14-V1"
+ CACHEKEY: "bionic_coq-V2019-01-28-V1"
IMAGE: "$CI_REGISTRY_IMAGE:$CACHEKEY"
# By default, jobs run in the base switch; override to select another switch
OPAM_SWITCH: "base"
@@ -288,16 +288,15 @@ pkg:opam:
variables:
OPAM_SWITCH: edge
-pkg:nix:
+.nix-template: &nix-template
image: nixorg/nix:latest # Minimal NixOS image which doesn't even contain git
stage: test
variables:
# By default we use coq.cachix.org as an extra substituter but this can be overridden
EXTRA_SUBSTITUTERS: https://coq.cachix.org
- EXTRA_PUBLIC_KEYS: coq.cachix.org-1:Jgt0DwGAUo+wpxCM52k2V+E0hLoOzFPzvg94F65agtI=
+ EXTRA_PUBLIC_KEYS: coq.cachix.org-1:5QW/wwEnD+l2jvN6QRbRRsa4hBHG3QiQQ26cxu1F5tI=
# The following variables should not be overridden
GIT_STRATEGY: none
- CACHIX_PUBLIC_KEY: cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM=
NIXOS_PUBLIC_KEY: cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
dependencies: [] # We don't need to download build artifacts
@@ -305,8 +304,6 @@ pkg:nix:
script:
# Use current worktree as tmpdir to allow exporting artifacts in case of failure
- export TMPDIR=$PWD
- # Install Cachix as documented at https://github.com/cachix/cachix
- - nix-env -if https://github.com/cachix/cachix/tarball/master --substituters https://cachix.cachix.org --trusted-public-keys "$CACHIX_PUBLIC_KEY"
# We build an expression rather than a direct URL to not be dependent on
# the URL location; we are forced to put the public key of cache.nixos.org
# because there is no --extra-trusted-public-key option.
@@ -317,6 +314,24 @@ pkg:nix:
paths:
- nix-build-coq.drv-0/*/test-suite/logs
+pkg:nix:deploy:
+ <<: *nix-template
+ environment:
+ name: cachix
+ url: https://coq.cachix.org
+ before_script:
+ # Install Cachix as documented at https://github.com/cachix/cachix
+ - nix-env -iA cachix -f https://cachix.org/api/v1/install
+ only:
+ - master
+ - /^v.*\..*$/
+
+pkg:nix:
+ <<: *nix-template
+ except:
+ - master
+ - /^v.*\..*$/
+
doc:refman:
<<: *doc-template
dependencies:
@@ -386,11 +401,11 @@ test-suite:edge+trunk+make:
stage: test
dependencies: []
script:
- - opam switch create 4.08.0 --empty
+ - opam switch create 4.09.0 --empty
- eval $(opam env)
- - opam repo add ocaml-pr https://github.com/ocaml/ocaml-pr-repository.git
+ - opam repo add ocaml-beta https://github.com/ocaml/ocaml-beta-repository.git
- opam update
- - opam install ocaml-variants=4.08.0 num
+ - opam install ocaml-variants=4.09.0+trunk num
- eval $(opam env)
# We avoid problems with warnings:
- ./configure -profile devel -warn-error no
@@ -410,18 +425,18 @@ test-suite:edge+trunk+dune:
stage: test
dependencies: []
script:
- - opam switch create 4.08.0 --empty
+ - opam switch create 4.09.0 --empty
- eval $(opam env)
- - opam repo add ocaml-pr https://github.com/ocaml/ocaml-pr-repository.git
+ - opam repo add ocaml-beta https://github.com/ocaml/ocaml-beta-repository.git
- opam update
- - opam install ocaml-variants=4.08.0 num
+ - opam install ocaml-variants=4.09.0+trunk num
- opam pin add dune --dev # ounit lablgtk conf-gtksourceview
- opam install dune
- eval $(opam env)
# We use the release profile to avoid problems with warnings
- make -f Makefile.dune trunk
- export COQ_UNIT_TEST=noop
- - dune runtest --profile=ocaml408
+ - dune runtest --profile=ocaml409
variables:
OPAM_SWITCH: edge
artifacts:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 855d36048d..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,116 +0,0 @@
-dist: trusty
-
-# Travis builds are slower using sudo: false (the container-based
-# infrastructure) as of March 2017; see
-# https://github.com/coq/coq/pull/467 for some discussion.
-sudo: required
-
-# Until Ocaml becomes a language, we set a known one.
-language: c
-
-cache:
- directories:
- - $HOME/.opam
-
-before_cache:
- - rm -rf ~/.opam/log/
-
-env:
- global:
- - NJOBS=2
- - COMPILER="4.07.0"
- - DUNE_VER=".1.2.1"
- - FINDLIB_VER=".1.8.0"
- - LABLGTK="lablgtk.2.18.6 conf-gtksourceview.2"
- - NATIVE_COMP="yes"
- - COQ_DEST="-local"
- - MAIN_TARGET="world"
-
-matrix:
- include:
- - os: osx
- env:
- - TEST_TARGET="test-suite"
- - NATIVE_COMP="no"
- - COQ_DEST="-local"
- - EXTRA_OPAM="ounit"
- before_install:
- - brew update
- - brew unlink python
- - brew install gnu-time
- # only way to continue using OPAM 1.2
- - brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/d156edeeed7291f4bc1e08620b331bbd05d52b78/Formula/opam.rb
- - opam init -j "$NJOBS" --compiler="$COMPILER" -n -y
- - opam switch "$COMPILER" && opam update
- - eval $(opam config env)
- - opam config list
- - opam install -j "$NJOBS" -y num ocamlfind${FINDLIB_VER} dune${DUNE_VER} ${EXTRA_OPAM}
- - opam list
-
- - if: NOT (type = pull_request)
- os: osx
- osx_image: xcode7.3
- env:
- - TEST_TARGET=""
- - NATIVE_COMP="no"
- - COQ_DEST="-prefix $PWD/_install_ci"
- - EXTRA_CONF="-coqide opt -warn-error yes"
- - EXTRA_OPAM="$LABLGTK"
- before_install:
- - brew update
- - brew unlink python
- - brew install gnu-time gtk+ expat gtksourceview gdk-pixbuf
- # only way to continue using OPAM 1.2
- - brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/d156edeeed7291f4bc1e08620b331bbd05d52b78/Formula/opam.rb
- - brew unlink python@2
- - brew install python3
- - pip3 install macpack
- - opam init -j "$NJOBS" --compiler="$COMPILER" -n -y
- - opam switch "$COMPILER" && opam update
- - eval $(opam config env)
- - opam config list
- - opam install -j "$NJOBS" -y num ocamlfind${FINDLIB_VER} dune${DUNE_VER} ${EXTRA_OPAM}
- - opam list
- before_deploy:
- - dev/build/osx/make-macos-dmg.sh
- deploy:
- - provider: bintray
- user: maximedenes
- file: .bintray.json
- key:
- secure: "gUvXWwWR0gicDqsKOnBfe45taToSFied6gN8tCa5IOtl6E6gFoHoPZ83ZWXQsZP50oMDFS5eji0VQAFGEbOsGrTZaD9Y9Jnu34NND78SWL1tsJ6nHO3aCAoMpB0N3+oRuF6S+9HStU6KXWqgj+GeU4vZ4TOlG01RGctJa6U3vII="
- skip_cleanup: true
- on:
- all_branches: true
-
-before_install:
-- if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then echo "Tested commit (followed by parent commits):"; git log -1; for commit in `git log -1 --format="%P"`; do echo; git log -1 $commit; done; fi
-
-script:
-
-- set -e
-- echo 'Testing make clean...' && echo -en 'travis_fold:start:coq.clean\\r'
-- make clean # ensure that `make clean` works on a fresh clone
-- echo -en 'travis_fold:end:coq.clean\\r'
-
-- echo 'Configuring Coq...' && echo -en 'travis_fold:start:coq.config\\r'
-- ./configure $COQ_DEST -warn-error yes -native-compiler $NATIVE_COMP $EXTRA_CONF
-- echo -en 'travis_fold:end:coq.config\\r'
-
-- echo 'Building Coq...' && echo -en 'travis_fold:start:coq.build\\r'
-- make -j $NJOBS $MAIN_TARGET
-- echo -en 'travis_fold:end:coq.build\\r'
-
-- echo 'Running tests...' && echo -en 'travis_fold:start:coq.test\\r'
-- if [ -n "$TEST_TARGET" ]; then $TW make -j $NJOBS $TEST_TARGET; fi
-- echo -en 'travis_fold:end:coq.test\\r'
-- set +e
-
-# Testing Gitter webhook
-notifications:
- webhooks:
- urls:
- - https://webhooks.gitter.im/e/3cdabdec318214c7cd63
- on_success: change # options: [always|never|change] default: always
- on_failure: always # options: [always|never|change] default: always
- on_start: never # options: [always|never|change] default: always
diff --git a/CHANGES.md b/CHANGES.md
index bcdb951a94..1a0b53f84a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -22,6 +22,11 @@ Coqide
Coqtop
+- the use of `coqtop` as a compiler has been deprecated, in favor of
+ `coqc`. Consequently option `-compile` will stop to be accepted in
+ the next release. `coqtop` is now reserved to interactive
+ use. (@ejgallego #9095)
+
- new option -topfile filename, which will set the current module name
(à la -top) based on the filename passed, taking into account the
proper -R/-Q options. For example, given -R Foo foolib using
@@ -39,6 +44,10 @@ Specification language, type inference
solved by writing an explicit `return` clause, sometimes even simply
an explicit `return _` clause.
+Kernel
+
+- Added primitive integers
+
Notations
- New command `Declare Scope` to explicitly declare a scope name
@@ -49,6 +58,9 @@ Notations
- New command `String Notation` to register string syntax for custom
inductive types.
+- Various bugs have been fixed (e.g. PR #9214 on removing spurious
+ parentheses on abbreviations shortening a strict prefix of an application).
+
Plugins
- The quote plugin (https://coq.inria.fr/distrib/V8.8.1/refman/proof-engine/detailed-tactic-examples.html#quote)
@@ -75,6 +87,14 @@ Tactics
foo : database`). When the database name is omitted, the hint is added to the
core database (as previously), but a deprecation warning is emitted.
+- There are now tactics in `PreOmega.v` called
+ `Z.div_mod_to_equations`, `Z.quot_rem_to_equations`, and
+ `Z.to_euclidean_division_equations` (which combines the `div_mod`
+ and `quot_rem` variants) which allow `lia`, `nia`, `romega`, etc to
+ support `Z.div` and `Z.modulo` (`Z.quot` and `Z.rem`, respectively),
+ by posing the specifying equation for `Z.div` and `Z.modulo` before
+ replacing them with atoms.
+
Vernacular commands
- `Combined Scheme` can now work when inductive schemes are generated in sort
@@ -101,6 +121,11 @@ Vernacular commands
- Option `Refine Instance Mode` has been turned off by default, meaning that
`Instance` no longer opens a proof when a body is provided.
+- `Instance`, when no body is provided, now always opens a proof. This is a
+ breaking change, as instance of `Instance foo : C.` where `C` is a trivial
+ class will have to be changed into `Instance foo : C := {}.` or
+ `Instance foo : C. Proof. Qed.`.
+
Tools
- The `-native-compiler` flag of `coqc` and `coqtop` now takes an argument which can have three values:
@@ -134,6 +159,8 @@ Standard Library
- Added `Coq.Structures.OrderedTypeEx.String_as_OT` to make strings an
ordered type (using lexical order).
+- The `Coq.Numbers.Cyclic.Int31` library is deprecated.
+
Universes
- Added `Print Universes Subgraph` variant of `Print Universes`.
@@ -161,12 +188,24 @@ Misc
SSReflect
- New intro patterns:
- - temporary introduction: => +
- - block introduction: => [^ prefix ] [^~ suffix ]
- - fast introduction: => >
- - tactics as views: => /ltac:mytac
+ - temporary introduction: `=> +`
+ - block introduction: `=> [^ prefix ] [^~ suffix ]`
+ - fast introduction: `=> >`
+ - tactics as views: `=> /ltac:mytac`
+ - replace hypothesis: `=> {}H`
See the reference manual for the actual documentation.
+- Clear discipline made consistent across the entire proof language.
+ Whenever a clear switch `{x..}` comes immediately before an existing proof
+ context entry (used as a view, as a rewrite rule or as name for a new
+ context entry) then such entry is cleared too.
+
+ E.g. The following sentences are elaborated as follows (when H is an existing
+ proof context entry):
+ - `=> {x..} H` -> `=> {x..H} H`
+ - `=> {x..} /H` -> `=> /v {x..H}`
+ - `rewrite {x..} H` -> `rewrite E {x..H}`
+
Changes from 8.8.2 to 8.9+beta1
===============================
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index de7fb9183c..bb0e388cdd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -55,7 +55,7 @@ please add an entry to [`dev/doc/critical-bugs`](/dev/doc/critical-bugs).
Don't be alarmed if the pull request process takes some time. It can take a few days to get feedback, approval on the final changes, and then a merge. Coq doesn't release new versions very frequently so it can take a few months for your change to land in a released version. That said, you can start using the latest Coq `master` branch to take advantage of all the new features, improvements, and fixes.
-Whitespace discipline (do not indent using tabs, no trailing spaces, text files end with newlines) is checked by Travis (using `git diff --check`). We ship a [`dev/tools/pre-commit`](/dev/tools/pre-commit) git hook which fixes these errors at commit time. `configure` automatically sets you up to use it, unless you already have a hook at `.git/hooks/pre-commit`.
+Whitespace discipline (do not indent using tabs, no trailing spaces, text files end with newlines) is checked by the `lint` job on GitLab CI (using `git diff --check`). We ship a [`dev/tools/pre-commit`](/dev/tools/pre-commit) git hook which fixes these errors at commit time. `configure` automatically sets you up to use it, unless you already have a hook at `.git/hooks/pre-commit`.
Here are a few tags Coq developers may add to your PR and what they mean. In general feedback and requests for you as the pull request author will be in the comments and tags are only used to organize pull requests.
diff --git a/INSTALL b/INSTALL
index 8d8efd4d4d..44ea195f59 100644
--- a/INSTALL
+++ b/INSTALL
@@ -113,9 +113,8 @@ INSTALLATION PROCEDURE IN DETAILS (NORMAL USERS).
"./configure -help". The main options accepted are:
-prefix <dir>
- Binaries, library, man pages and Emacs mode will be respectively
- installed in <dir>/bin, <dir>/lib/coq, <dir>/man and
- <dir>/lib/emacs/site-lisp
+ Binaries, library, and man pages will be respectively
+ installed in <dir>/bin, <dir>/lib/coq, and <dir>/man
-bindir <dir> (default: /usr/local/bin)
Directory where the binaries will be installed
@@ -126,9 +125,6 @@ INSTALLATION PROCEDURE IN DETAILS (NORMAL USERS).
-mandir <dir> (default: /usr/local/share/man)
Directory where the Coq manual pages will be installed
--emacslib <dir> (default: /usr/local/lib/emacs/site-lisp)
- Directory where the Coq Emacs mode will be installed
-
-arch <value> (default is the result of the command "arch")
An arbitrary architecture name for your machine (useful when
compiling Coq on two different architectures for which the
@@ -175,9 +171,9 @@ INSTALLATION PROCEDURE IN DETAILS (NORMAL USERS).
it is recommended to compile in parallel, via make -jN where N is your number
of cores.
-5- You can now install the Coq system. Executables, libraries, manual pages
- and emacs mode are copied in some standard places of your system, defined at
- configuration time (step 3). Just do
+5- You can now install the Coq system. Executables, libraries, and
+ manual pages are copied in some standard places of your system,
+ defined at configuration time (step 3). Just do
umask 022
make install
diff --git a/META.coq.in b/META.coq.in
index 159984d87a..ab142ccc43 100644
--- a/META.coq.in
+++ b/META.coq.in
@@ -411,30 +411,6 @@ package "plugins" (
archive(native) = "nsatz_plugin.cmx"
)
- package "natsyntax" (
-
- description = "Coq natsyntax plugin"
- version = "8.10"
-
- requires = ""
- directory = "syntax"
-
- archive(byte) = "nat_syntax_plugin.cmo"
- archive(native) = "nat_syntax_plugin.cmx"
- )
-
- package "zsyntax" (
-
- description = "Coq zsyntax plugin"
- version = "8.10"
-
- requires = ""
- directory = "syntax"
-
- archive(byte) = "z_syntax_plugin.cmo"
- archive(native) = "z_syntax_plugin.cmx"
- )
-
package "rsyntax" (
description = "Coq rsyntax plugin"
@@ -447,16 +423,16 @@ package "plugins" (
archive(native) = "r_syntax_plugin.cmx"
)
- package "int31syntax" (
+ package "int63syntax" (
- description = "Coq int31syntax plugin"
+ description = "Coq int63syntax plugin"
version = "8.10"
requires = ""
directory = "syntax"
- archive(byte) = "int31_syntax_plugin.cmo"
- archive(native) = "int31_syntax_plugin.cmx"
+ archive(byte) = "int63_syntax_plugin.cmo"
+ archive(native) = "int63_syntax_plugin.cmx"
)
package "string_notation" (
diff --git a/Makefile b/Makefile
index 99d4611dce..a82927f8cf 100644
--- a/Makefile
+++ b/Makefile
@@ -82,7 +82,8 @@ export MLPACKFILES := $(call find, '*.mlpack')
export MLGFILES := $(call find, '*.mlg')
export CFILES := $(call findindir, 'kernel/byterun', '*.c')
-MERLININFILES := $(call find, '.merlin.in')
+# NB our find wrapper ignores the test suite
+MERLININFILES := $(call find, '.merlin.in') test-suite/unit-tests/.merlin.in
export MERLINFILES := $(MERLININFILES:.in=)
# NB: The lists of currently existing .ml and .mli files will change
@@ -99,7 +100,7 @@ GENMLGFILES:= $(MLGFILES:.mlg=.ml)
export GRAMFILES=$(addprefix gramlib/.pack/gramlib__,Ploc Plexing Gramext Grammar)
export GRAMMLFILES := $(addsuffix .ml, $(GRAMFILES)) $(addsuffix .mli, $(GRAMFILES))
export GENGRAMFILES := $(GRAMMLFILES) gramlib/.pack/gramlib.ml
-export GENMLFILES:=$(LEXFILES:.mll=.ml) $(YACCFILES:.mly=.ml) $(GENMLGFILES) ide/coqide_os_specific.ml kernel/copcodes.ml
+export GENMLFILES:=$(LEXFILES:.mll=.ml) $(YACCFILES:.mly=.ml) $(GENMLGFILES) ide/coqide_os_specific.ml kernel/copcodes.ml kernel/uint63.ml
export GENHFILES:=kernel/byterun/coq_jumptbl.h
export GENFILES:=$(GENMLFILES) $(GENMLIFILES) $(GENHFILES)
diff --git a/Makefile.build b/Makefile.build
index e683a6bda8..26e2819990 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -198,7 +198,7 @@ TIMER=$(if $(TIMED), $(STDTIME), $(TIMECMD))
# TIME="%C (%U user, %S sys, %e total, %M maxres)"
COQOPTS=$(NATIVECOMPUTE) $(COQWARNERROR) $(COQUSERFLAGS)
-BOOTCOQC=$(TIMER) $(COQTOPBEST) -boot $(COQOPTS) -compile
+BOOTCOQC=$(TIMER) $(COQC) -boot $(COQOPTS)
LOCALINCLUDES=$(addprefix -I ,$(SRCDIRS))
MLINCLUDES=$(LOCALINCLUDES)
@@ -281,7 +281,7 @@ ifndef ORDER_ONLY_SEP
$(error This Makefile needs GNU Make 3.81 or later (that is a version that supports the order-only dependency feature without major bugs.))
endif
-VO_TOOLS_DEP := $(COQTOPBEST)
+VO_TOOLS_DEP := $(COQC)
ifdef VALIDATE
VO_TOOLS_DEP += $(CHICKEN)
endif
@@ -338,6 +338,13 @@ $(COQPP): $(COQPPCMO) coqpp/coqpp_main.ml
$(HIDE)$(OCAMLC) -I coqpp $^ -linkall -o $@
###########################################################################
+# Specific rules for Uint63
+###########################################################################
+kernel/uint63.ml: kernel/write_uint63.ml kernel/uint63_x86.ml kernel/uint63_amd64.ml
+ $(SHOW)'WRITE $@'
+ $(HIDE)(cd kernel && ocaml unix.cma $(shell basename $<))
+
+###########################################################################
# Main targets (coqtop.opt, coqtop.byte)
###########################################################################
@@ -351,6 +358,9 @@ coqbyte: $(TOPBYTE) $(CHICKENBYTE)
$(COQTOPEXE): $(TOPBINOPT:.opt=.$(BEST))
rm -f $@ && cp $< $@
+$(COQC): $(COQCOPT:.opt=.$(BEST))
+ rm -f $@ && cp $< $@
+
bin/%.opt$(EXE): topbin/%_bin.ml $(LINKCMX) $(LIBCOQRUN)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLOPT) -linkall -linkpkg $(MLINCLUDES) \
@@ -377,17 +387,6 @@ $(COQTOPBYTE): $(LINKCMO) $(LIBCOQRUN) $(COQTOP_BYTE)
$(SYSMOD) -package compiler-libs.toplevel \
$(LINKCMO) $(BYTEFLAGS) $(COQTOP_BYTE) -o $@
-# For coqc
-COQCCMO:=config/config.cma clib/clib.cma lib/lib.cma toplevel/usage.cmo tools/coqc.cmo
-
-$(COQC): $(call bestobj, $(COQCCMO))
- $(SHOW)'OCAMLBEST -o $@'
- $(HIDE)$(call bestocaml, $(SYSMOD))
-
-$(COQCBYTE): $(COQCCMO)
- $(SHOW)'OCAMLC -o $@'
- $(HIDE)$(call ocamlbyte, $(SYSMOD))
-
###########################################################################
# other tools
###########################################################################
@@ -512,7 +511,7 @@ $(FAKEIDEBYTE): $(FAKEIDECMO) | $(IDETOPBYTE)
# votour: a small vo explorer (based on the checker)
-VOTOURCMO:=clib/cObj.cmo checker/analyze.cmo checker/values.cmo checker/votour.cmo
+VOTOURCMO:=clib/cObj.cmo kernel/uint63.cmo checker/analyze.cmo checker/values.cmo checker/votour.cmo
bin/votour: $(call bestobj, $(VOTOURCMO))
$(SHOW)'OCAMLBEST -o $@'
@@ -784,8 +783,7 @@ $(PLUGMLLIBDFILE).d: $(D_DEPEND_BEFORE_SRC) $(filter plugins/%, $(MLLIBFILES) $(
coqlib: theories plugins
ifdef QUICK
$(SHOW)'COQC -schedule-vio2vo $(NJOBS) theories/**.vio plugins/**.vio'
- $(HIDE)$(BOOTCOQC:-compile=-schedule-vio2vo) $(NJOBS) \
- $(THEORIESVO) $(PLUGINSVO)
+ $(HIDE)$(BOOTCOQC) -schedule-vio2vo $(NJOBS) $(THEORIESVO) $(PLUGINSVO)
endif
coqlib.timing.diff: theories.timing.diff plugins.timing.diff
diff --git a/Makefile.common b/Makefile.common
index 2dced04967..8292158ef8 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -32,6 +32,7 @@ COQWCBYTE:=bin/coqwc.byte$(EXE)
COQDOC:=bin/coqdoc$(EXE)
COQDOCBYTE:=bin/coqdoc.byte$(EXE)
COQC:=bin/coqc$(EXE)
+COQCOPT:=bin/coqc.opt$(EXE)
COQCBYTE:=bin/coqc.byte$(EXE)
COQWORKMGR:=bin/coqworkmgr$(EXE)
COQWORKMGRBYTE:=bin/coqworkmgr.byte$(EXE)
@@ -139,7 +140,7 @@ BTAUTOCMO:=plugins/btauto/btauto_plugin.cmo
RTAUTOCMO:=plugins/rtauto/rtauto_plugin.cmo
SYNTAXCMO:=$(addprefix plugins/syntax/, \
r_syntax_plugin.cmo \
- int31_syntax_plugin.cmo \
+ int63_syntax_plugin.cmo \
numeral_notation_plugin.cmo \
string_notation_plugin.cmo)
DERIVECMO:=plugins/derive/derive_plugin.cmo
diff --git a/Makefile.dune b/Makefile.dune
index ee3e2d6cb7..78ecc4b056 100644
--- a/Makefile.dune
+++ b/Makefile.dune
@@ -40,7 +40,7 @@ help:
voboot:
dune build $(DUNEOPT) @vodeps
- dune exec coq_dune $(BUILD_CONTEXT)/.vfiles.d
+ dune exec ./tools/coq_dune.exe $(BUILD_CONTEXT)/.vfiles.d
states: voboot
dune build $(DUNEOPT) theories/Init/Prelude.vo
diff --git a/README.md b/README.md
index e8300ca552..5df8423ef4 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,6 @@
[![GitLab][gitlab-badge]][gitlab-link]
[![Azure Pipelines][azure-badge]][azure-link]
-[![Travis][travis-badge]][travis-link]
-[![Appveyor][appveyor-badge]][appveyor-link]
[![Gitter][gitter-badge]][gitter-link]
[![DOI][doi-badge]][doi-link]
@@ -13,12 +11,6 @@
[azure-badge]: https://dev.azure.com/coq/coq/_apis/build/status/coq.coq?branchName=master
[azure-link]: https://dev.azure.com/coq/coq/_build/latest?definitionId=1?branchName=master
-[travis-badge]: https://travis-ci.org/coq/coq.svg?branch=master
-[travis-link]: https://travis-ci.org/coq/coq/builds
-
-[appveyor-badge]: https://ci.appveyor.com/api/projects/status/eln43k05pa2vm908/branch/master?svg=true
-[appveyor-link]: https://ci.appveyor.com/project/coq/coq/branch/master
-
[gitter-badge]: https://badges.gitter.im/coq/coq.svg
[gitter-link]: https://gitter.im/coq/coq
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 7420856214..0000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-version: '{branch}~{build}'
-clone_depth: 10
-
-cache:
- - C:\cygwin64 -> dev\ci\appveyor.bat, dev\ci\appveyor.sh
-
-platform:
-- x64
-
-image:
-- Visual Studio 2017
-
-environment:
- CYGMIRROR: http://ftp.inf.tu-dresden.de/software/windows/cygwin32
- matrix:
- - USEOPAM: true
- ARCH: 64
-
-build_script:
-- cmd: 'call %APPVEYOR_BUILD_FOLDER%\dev\ci\appveyor.bat'
-
-test: off
diff --git a/checker/analyze.ml b/checker/analyze.ml
index 63324bff20..77e70318dd 100644
--- a/checker/analyze.ml
+++ b/checker/analyze.ml
@@ -106,6 +106,7 @@ end
type repr =
| RInt of int
+| RInt63 of Uint63.t
| RBlock of (int * int) (* tag × len *)
| RString of string
| RPointer of int
@@ -119,6 +120,7 @@ type data =
type obj =
| Struct of int * data array (* tag × data *)
+| Int63 of Uint63.t (* Primitive integer *)
| String of string
module type Input =
@@ -255,6 +257,28 @@ let input_header64 chan =
in
(tag, len)
+let input_cstring chan : string =
+ let buff = Buffer.create 17 in
+ let rec loop () =
+ match input_char chan with
+ | '\o000' -> Buffer.contents buff
+ | c -> Buffer.add_char buff c |> loop
+ in loop ()
+
+let input_intL chan : int64 =
+ let i = input_byte chan in
+ let j = input_byte chan in
+ let k = input_byte chan in
+ let l = input_byte chan in
+ let m = input_byte chan in
+ let n = input_byte chan in
+ let o = input_byte chan in
+ let p = input_byte chan in
+ let ( lsl ) x y = Int64.(shift_left (of_int x) y) in
+ let ( lor ) = Int64.logor in
+ (i lsl 56) lor (j lsl 48) lor (k lsl 40) lor (l lsl 32) lor
+ (m lsl 24) lor (n lsl 16) lor (o lsl 8) lor (Int64.of_int p)
+
let parse_object chan =
let data = input_byte chan in
if prefix_small_block <= data then
@@ -297,6 +321,11 @@ let parse_object chan =
let addr = input_int32u chan in
for _i = 0 to 15 do ignore (input_byte chan); done;
RCode addr
+ | CODE_CUSTOM ->
+ begin match input_cstring chan with
+ | "_j" -> RInt63 (Uint63.of_int64 (input_intL chan))
+ | s -> Printf.eprintf "Unhandled custom code: %s" s; assert false
+ end
| CODE_DOUBLE_ARRAY32_LITTLE
| CODE_DOUBLE_BIG
| CODE_DOUBLE_LITTLE
@@ -304,8 +333,7 @@ let parse_object chan =
| CODE_DOUBLE_ARRAY8_LITTLE
| CODE_DOUBLE_ARRAY32_BIG
| CODE_INFIXPOINTER
- | CODE_CUSTOM ->
- Printf.eprintf "Unhandled code %04x\n%!" data; assert false
+ -> Printf.eprintf "Unhandled code %04x\n%!" data; assert false
let parse chan =
let (magic, len, _, _, size) = parse_header chan in
@@ -337,6 +365,11 @@ let parse chan =
| RCode addr ->
let data = Fun addr in
data, None
+ | RInt63 i ->
+ let data = Ptr !current_object in
+ let () = LargeArray.set memory !current_object (Int63 i) in
+ let () = incr current_object in
+ data, None
in
let rec fill block off accu =
@@ -400,6 +433,7 @@ let instantiate (p, mem) =
for i = 0 to len - 1 do
let obj = match LargeArray.get mem i with
| Struct (tag, blk) -> Obj.new_block tag (Array.length blk)
+ | Int63 i -> Obj.repr i
| String str -> Obj.repr str
in
LargeArray.set ans i obj
@@ -418,6 +452,7 @@ let instantiate (p, mem) =
for k = 0 to Array.length blk - 1 do
Obj.set_field obj k (get_data blk.(k))
done
+ | Int63 _
| String _ -> ()
done;
get_data p
diff --git a/checker/analyze.mli b/checker/analyze.mli
index d7770539df..029f595959 100644
--- a/checker/analyze.mli
+++ b/checker/analyze.mli
@@ -1,3 +1,4 @@
+(** Representation of data allocated on the OCaml heap. *)
type data =
| Int of int
| Ptr of int
@@ -6,6 +7,7 @@ type data =
type obj =
| Struct of int * data array (* tag × data *)
+| Int63 of Uint63.t (* Primitive integer *)
| String of string
module LargeArray :
diff --git a/checker/checkInductive.ml b/checker/checkInductive.ml
index c823db956d..d2d1efcb2c 100644
--- a/checker/checkInductive.ml
+++ b/checker/checkInductive.ml
@@ -77,6 +77,9 @@ let check_arity env ar1 ar2 = match ar1, ar2 with
(* template_level is inferred by indtypes, so functor application can produce a smaller one *)
| (RegularArity _ | TemplateArity _), _ -> false
+let check_kelim k1 k2 =
+ List.for_all (fun x -> List.mem_f Sorts.family_equal x k2) k1
+
(* Use [eq_ind_chk] because when we rebuild the recargs we have lost
the knowledge of who is the canonical version.
Try with to see test-suite/coqchk/include.v *)
@@ -102,7 +105,7 @@ let check_packet env mind ind
check "mind_user_lc" (Array.equal Constr.equal ind.mind_user_lc mind_user_lc);
check "mind_nrealargs" Int.(equal ind.mind_nrealargs mind_nrealargs);
check "mind_nrealdecls" Int.(equal ind.mind_nrealdecls mind_nrealdecls);
- check "mind_kelim" (List.equal Sorts.family_equal ind.mind_kelim mind_kelim);
+ check "mind_kelim" (check_kelim ind.mind_kelim mind_kelim);
check "mind_nf_lc" (Array.equal Constr.equal ind.mind_nf_lc mind_nf_lc);
(* NB: here syntactic equality is not just an optimisation, we also
diff --git a/checker/mod_checking.ml b/checker/mod_checking.ml
index 086dd17e39..c33c6d5d09 100644
--- a/checker/mod_checking.ml
+++ b/checker/mod_checking.ml
@@ -66,6 +66,7 @@ let mk_mtb mp sign delta =
let rec check_module env mp mb =
Flags.if_verbose Feedback.msg_notice (str " checking module: " ++ str (ModPath.to_string mp));
+ let env = Modops.add_retroknowledge mb.mod_retroknowledge env in
let (_:module_signature) =
check_signature env mb.mod_type mb.mod_mp mb.mod_delta
in
diff --git a/checker/safe_checking.ml b/checker/safe_checking.ml
index 6dc2953060..4a64039e30 100644
--- a/checker/safe_checking.ml
+++ b/checker/safe_checking.ml
@@ -16,6 +16,7 @@ let import senv clib univs digest =
let env = Safe_typing.env_of_safe_env senv in
let env = push_context_set ~strict:true mb.mod_constraints env in
let env = push_context_set ~strict:true univs env in
+ let env = Modops.add_retroknowledge mb.mod_retroknowledge env in
Mod_checking.check_module env mb.mod_mp mb;
let (_,senv) = Safe_typing.import clib univs digest senv in senv
diff --git a/checker/validate.ml b/checker/validate.ml
index b85944f94f..72cf38ebe6 100644
--- a/checker/validate.ml
+++ b/checker/validate.ml
@@ -86,6 +86,7 @@ let rec val_gen v ctx o = match v with
| Annot (s,v) -> val_gen v (ctx/CtxAnnot s) o
| Dyn -> val_dyn ctx o
| Proxy { contents = v } -> val_gen v ctx o
+ | Uint63 -> val_uint63 ctx o
(* Check that an object is a tuple (or a record). vs is an array of
value representation for each field. Its size corresponds to the
@@ -133,6 +134,10 @@ and val_array v ctx o =
val_gen v ctx (Obj.field o i)
done
+and val_uint63 ctx o =
+ if not (Uint63.is_uint63 o) then
+ fail ctx o "not a 63-bit unsigned integer"
+
let print_frame = function
| CtxType t -> t
| CtxAnnot t -> t
diff --git a/checker/values.ml b/checker/values.ml
index 1afe764ca4..7ca2dc8050 100644
--- a/checker/values.ml
+++ b/checker/values.ml
@@ -34,6 +34,7 @@ type value =
| Dyn
| Proxy of value ref
+ | Uint63
let fix (f : value -> value) : value =
let self = ref Any in
@@ -151,7 +152,8 @@ let rec v_constr =
[|v_caseinfo;v_constr;v_constr;Array v_constr|]; (* Case *)
[|v_fix|]; (* Fix *)
[|v_cofix|]; (* CoFix *)
- [|v_proj;v_constr|] (* Proj *)
+ [|v_proj;v_constr|]; (* Proj *)
+ [|Uint63|] (* Int *)
|])
and v_prec = Tuple ("prec_declaration",
@@ -214,9 +216,12 @@ let v_oracle =
let v_pol_arity =
v_tuple "polymorphic_arity" [|List(Opt v_level);v_univ|]
+let v_primitive =
+ v_enum "primitive" 25
+
let v_cst_def =
v_sum "constant_def" 0
- [|[|Opt Int|]; [|v_cstr_subst|]; [|v_lazy_constr|]|]
+ [|[|Opt Int|]; [|v_cstr_subst|]; [|v_lazy_constr|]; [|v_primitive|]|]
let v_typing_flags =
v_tuple "typing_flags" [|v_bool; v_bool; v_oracle; v_bool; v_bool; v_bool; v_bool|]
@@ -288,6 +293,20 @@ let v_ind_pack = v_tuple "mutual_inductive_body"
Opt v_bool;
v_typing_flags|]
+let v_prim_ind = v_enum "prim_ind" 4
+
+let v_prim_type = v_enum "prim_type" 1
+
+let v_retro_action =
+ v_sum "retro_action" 0 [|
+ [|v_prim_ind; v_ind|];
+ [|v_prim_type; v_cst|];
+ [|v_cst|];
+ |]
+
+let v_retroknowledge =
+ v_sum "module_retroknowledge" 1 [|[|List v_retro_action|]|]
+
let rec v_mae =
Sum ("module_alg_expr",0,
[|[|v_mp|]; (* SEBident *)
@@ -318,7 +337,7 @@ and v_impl =
and v_noimpl = v_unit
and v_module =
Tuple ("module_body",
- [|v_mp;v_impl;v_sign;Opt v_mexpr;v_context_set;v_resolver;Any|])
+ [|v_mp;v_impl;v_sign;Opt v_mexpr;v_context_set;v_resolver;v_retroknowledge|])
and v_modtype =
Tuple ("module_type_body",
[|v_mp;v_noimpl;v_sign;Opt v_mexpr;v_context_set;v_resolver;v_unit|])
diff --git a/checker/values.mli b/checker/values.mli
index 616b69907f..2ab8da1928 100644
--- a/checker/values.mli
+++ b/checker/values.mli
@@ -38,6 +38,8 @@ type value =
| Proxy of value ref
(** Same as the inner value, used to define recursive types *)
+ | Uint63
+
(** NB: List and Opt have their own constructors to make it easy to
define eg [let rec foo = List foo]. *)
diff --git a/checker/votour.ml b/checker/votour.ml
index 3c088b59b5..36014cde73 100644
--- a/checker/votour.ml
+++ b/checker/votour.ml
@@ -100,6 +100,7 @@ struct
init_size seen (fun n -> fold (succ i) (accu + 1 + n) k) os.(i)
in
fold 0 1 (fun size -> let () = LargeArray.set !sizes p size in k size)
+ | Int63 _ -> k 0
| String s ->
let size = 2 + (String.length s / ws) in
let () = LargeArray.set !sizes p size in
@@ -116,6 +117,7 @@ struct
| Ptr p ->
match LargeArray.get !memory p with
| Struct (tag, os) -> BLOCK (tag, os)
+ | Int63 _ -> OTHER (* TODO: pretty-print int63 values *)
| String s -> STRING s
let input ch =
@@ -153,6 +155,7 @@ let rec get_name ?(extra=false) = function
|Annot (s,v) -> s^"/"^get_name ~extra v
|Dyn -> "<dynamic>"
| Proxy v -> get_name ~extra !v
+ | Uint63 -> "Uint63"
(** For tuples, its quite handy to display the inner 1st string (if any).
Cf. [structure_body] for instance *)
@@ -257,6 +260,7 @@ let rec get_children v o pos = match v with
end
|Fail s -> raise Forbidden
| Proxy v -> get_children !v o pos
+ | Uint63 -> raise Exit
let get_children v o pos =
try get_children v o pos
diff --git a/configure.ml b/configure.ml
index 6f5ade3b9a..ef38651a4d 100644
--- a/configure.ml
+++ b/configure.ml
@@ -19,7 +19,7 @@ let vo_magic = 8991
let state_magic = 58991
let distributed_exec =
["coqtop.opt"; "coqidetop.opt"; "coqqueryworker.opt"; "coqproofworker.opt"; "coqtacticworker.opt";
- "coqc";"coqchk";"coqdoc";"coqworkmgr";"coq_makefile";"coq-tex";"coqwc";"csdpcert";"coqdep"]
+ "coqc.opt";"coqchk";"coqdoc";"coqworkmgr";"coq_makefile";"coq-tex";"coqwc";"csdpcert";"coqdep"]
let verbose = ref false (* for debugging this script *)
diff --git a/default.nix b/default.nix
index 89d69cc40f..b65d736d79 100644
--- a/default.nix
+++ b/default.nix
@@ -23,10 +23,10 @@
{ pkgs ?
(import (fetchTarball {
- url = "https://github.com/NixOS/nixpkgs/archive/958a6c6dd39b0d6628e1408e798a8f1308f2f3e1.tar.gz";
- sha256 = "0vs6k4jn0rbdfzaxmh3xh64q213326680i9g3cjgr7l9y6h6m5sy";
+ url = "https://github.com/NixOS/nixpkgs/archive/11cf7d6e1ffd5fbc09a51b76d668ad0858a772ed.tar.gz";
+ sha256 = "0zcg4mgfdk3ryiqj1j5iv5bljjvsgi6q6j9z1vkq383c4g4clc72";
}) {})
-, ocamlPackages ? pkgs.ocaml-ng.ocamlPackages_4_06
+, ocamlPackages ? pkgs.ocamlPackages
, buildIde ? true
, buildDoc ? true
, doInstallCheck ? true
diff --git a/dev/build/windows/makecoq_mingw.sh b/dev/build/windows/makecoq_mingw.sh
index 07a13b8204..2e934ff0c0 100755
--- a/dev/build/windows/makecoq_mingw.sh
+++ b/dev/build/windows/makecoq_mingw.sh
@@ -444,9 +444,6 @@ function load_overlay_data {
else
export CI_BRANCH=""
export CI_PULL_REQUEST=""
- # Used when building 8.8.0 with the latest scripts
- export TRAVIS_BRANCH=""
- export TRAVIS_PULL_REQUEST=""
fi
for overlay in /build/user-overlays/*.sh; do
diff --git a/dev/ci/README-developers.md b/dev/ci/README-developers.md
index 6663fbecf8..98ea594366 100644
--- a/dev/ci/README-developers.md
+++ b/dev/ci/README-developers.md
@@ -16,14 +16,9 @@ We are currently running tests on the following platforms:
`./configure`. It should allow complying with this discipline
without pain.
-- Travis CI is used to test the compilation of Coq and run the test-suite on
- macOS.
-
-- AppVeyor is used to test the compilation of Coq and run the test-suite on
- Windows.
-
- Azure Pipelines is used to test the compilation of Coq and run the
- test-suite on Windows. It is expected to replace appveyor eventually.
+ test-suite on Windows and on macOS. It is expected to be used to build
+ macOS and Windows packages eventually.
You can anticipate the results of most of these tests prior to submitting your
PR by running GitLab CI on your private branches. To do so follow these steps:
diff --git a/dev/ci/appveyor.bat b/dev/ci/appveyor.bat
deleted file mode 100644
index 341b875edc..0000000000
--- a/dev/ci/appveyor.bat
+++ /dev/null
@@ -1,42 +0,0 @@
-REM This script either runs the test suite with OPAM (if USEOPAM is true) or
-REM builds the Coq binary packages for windows (if USEOPAM is false).
-
-if %ARCH% == 32 (
- SET ARCHLONG=i686
- SET CYGROOT=C:\cygwin
- SET SETUP=setup-x86.exe
-)
-
-if %ARCH% == 64 (
- SET ARCHLONG=x86_64
- SET CYGROOT=C:\cygwin64
- SET SETUP=setup-x86_64.exe
-)
-
-SET CYGCACHE=%CYGROOT%\var\cache\setup
-SET APPVEYOR_BUILD_FOLDER_MFMT=%APPVEYOR_BUILD_FOLDER:\=/%
-SET APPVEYOR_BUILD_FOLDER_CFMT=%APPVEYOR_BUILD_FOLDER_MFMT:C:/=/cygdrive/c/%
-SET DESTCOQ=C:\coq%ARCH%_inst
-SET COQREGTESTING=Y
-
-if %USEOPAM% == false (
- call %APPVEYOR_BUILD_FOLDER%\dev\build\windows\MakeCoq_MinGW.bat -threads=1 ^
- -arch=%ARCH% -installer=Y -coqver=%APPVEYOR_BUILD_FOLDER_CFMT% ^
- -destcyg=%CYGROOT% -destcoq=%DESTCOQ% -cygcache=%CYGCACHE% ^
- -addon=bignums -make=N ^
- -setup %CYGROOT%\%SETUP% || GOTO ErrorExit
- copy "%CYGROOT%\build\coq-local\dev\nsis\*.exe" dev\nsis || GOTO ErrorExit
- 7z a coq-opensource-archive-windows-%ARCHLONG%.zip %CYGROOT%\build\tarballs\* || GOTO ErrorExit
-)
-
-if %USEOPAM% == true (
- %CYGROOT%\%SETUP% -qnNdO -R %CYGROOT% -l %CYGCACHE% -s %CYGMIRROR% ^
- -P rsync -P patch -P diffutils -P make -P unzip -P m4 -P findutils -P time
- %CYGROOT%/bin/bash -l %APPVEYOR_BUILD_FOLDER%/dev/ci/appveyor.sh || GOTO ErrorExit
-)
-
-GOTO :EOF
-
-:ErrorExit
- ECHO ERROR %0 failed
- EXIT /b 1
diff --git a/dev/ci/ci-basic-overlay.sh b/dev/ci/ci-basic-overlay.sh
index 8dee465cf4..74e8d3bbaa 100755
--- a/dev/ci/ci-basic-overlay.sh
+++ b/dev/ci/ci-basic-overlay.sh
@@ -35,7 +35,7 @@
: "${unicoq_CI_GITURL:=https://github.com/unicoq/unicoq}"
: "${unicoq_CI_ARCHIVEURL:=${unicoq_CI_GITURL}/archive}"
-: "${mtac2_CI_REF:=master-sync}"
+: "${mtac2_CI_REF:=master}"
: "${mtac2_CI_GITURL:=https://github.com/Mtac2/Mtac2}"
: "${mtac2_CI_ARCHIVEURL:=${mtac2_CI_GITURL}/archive}"
diff --git a/dev/ci/ci-wrapper.sh b/dev/ci/ci-wrapper.sh
index 12a70176c2..9ca8f76054 100755
--- a/dev/ci/ci-wrapper.sh
+++ b/dev/ci/ci-wrapper.sh
@@ -6,13 +6,6 @@
set -eo pipefail
-function travis_fold {
- if [ -n "${TRAVIS}" ];
- then
- echo "travis_fold:$1:$2"
- fi
-}
-
CI_NAME="$1"
CI_SCRIPT="ci-${CI_NAME}.sh"
@@ -22,6 +15,5 @@ cd "${DIR}/../.."
export TIMED=1
"${DIR}/${CI_SCRIPT}" 2>&1 | tee time-of-build.log
-travis_fold 'start' 'coq.test.timing' && echo 'Aggregating timing log...'
+echo 'Aggregating timing log...'
python ./tools/make-one-time-file.py time-of-build.log
-travis_fold 'end' 'coq.test.timing'
diff --git a/dev/ci/docker/bionic_coq/Dockerfile b/dev/ci/docker/bionic_coq/Dockerfile
index baf470e021..4cd7faf757 100644
--- a/dev/ci/docker/bionic_coq/Dockerfile
+++ b/dev/ci/docker/bionic_coq/Dockerfile
@@ -1,4 +1,4 @@
-# CACHEKEY: "bionic_coq-V2018-12-14-V1"
+# CACHEKEY: "bionic_coq-V2019-01-28-V1"
# ^^ Update when modifying this file.
FROM ubuntu:bionic
@@ -38,7 +38,7 @@ ENV COMPILER="4.05.0"
# `num` does not have a version number as the right version to install varies
# with the compiler version.
ENV BASE_OPAM="num ocamlfind.1.8.0 dune.1.6.2 ounit.2.0.8 odoc.1.3.0" \
- CI_OPAM="menhir.20180530 elpi.1.1.0 ocamlgraph.1.8.8"
+ CI_OPAM="menhir.20181113 elpi.1.1.0 ocamlgraph.1.8.8"
# BASE switch; CI_OPAM contains Coq's CI dependencies.
ENV COQIDE_OPAM="lablgtk.2.18.5 conf-gtksourceview.2"
diff --git a/dev/ci/nix/CoLoR.nix b/dev/ci/nix/CoLoR.nix
index 4c5cfd83da..3fcf177aec 100644
--- a/dev/ci/nix/CoLoR.nix
+++ b/dev/ci/nix/CoLoR.nix
@@ -1,5 +1,5 @@
{ bignums }:
{
- buildInputs = [ bignums ];
+ coqBuildInputs = [ bignums ];
}
diff --git a/dev/ci/nix/Corn.nix b/dev/ci/nix/Corn.nix
index 18c7750279..0d22a6b91b 100644
--- a/dev/ci/nix/Corn.nix
+++ b/dev/ci/nix/Corn.nix
@@ -1,5 +1,5 @@
{ bignums, math-classes }:
{
- buildInputs = [ bignums math-classes ];
+ coqBuildInputs = [ bignums math-classes ];
}
diff --git a/dev/ci/nix/GeoCoq.nix b/dev/ci/nix/GeoCoq.nix
index a86fb2c44a..45d688285e 100644
--- a/dev/ci/nix/GeoCoq.nix
+++ b/dev/ci/nix/GeoCoq.nix
@@ -1,5 +1,5 @@
{ mathcomp }:
{
- buildInputs = [ mathcomp ];
+ coqBuildInputs = [ mathcomp ];
configure = "./configure.sh";
}
diff --git a/dev/ci/nix/README.md b/dev/ci/nix/README.md
index 1685b084e9..6f32abef95 100644
--- a/dev/ci/nix/README.md
+++ b/dev/ci/nix/README.md
@@ -17,3 +17,10 @@ build-system of that project: `configure`, `make`, and `clean`. Therefore, after
changing the working directory to the root of the sources of that project, the
contents of these variables can be evaluated to respectively set-up, build, and
clean the project.
+
+## Variant: nocoq
+
+The dependencies of the third-party developments are split into `buildInputs`
+and `coqBuildInputs`. The second list gathers the Coq libraries. In case you
+only want the non-coq dependencies (because you want to use Coq from your `PATH`),
+set the environment variable `NOCOQ` to some non-empty value.
diff --git a/dev/ci/nix/default.nix b/dev/ci/nix/default.nix
index 4acfae48e4..277e9ee08f 100644
--- a/dev/ci/nix/default.nix
+++ b/dev/ci/nix/default.nix
@@ -2,7 +2,8 @@
, branch
, wd
, project ? "xyz"
-, bn ? "release"
+, withCoq ? true
+, bn ? "master"
}:
with pkgs;
@@ -16,6 +17,11 @@ let mathcomp = coqPackages.mathcomp.overrideAttrs (o: {
name = "coq-git-mathcomp-git";
src = fetchTarball https://github.com/math-comp/math-comp/archive/master.tar.gz;
}); in
+let ssreflect = coqPackages.ssreflect.overrideAttrs (o: {
+ inherit (mathcomp) src;
+ }); in
+let coq-ext-lib = coqPackages.coq-ext-lib; in
+let simple-io = coqPackages.simple-io; in
let bignums = coqPackages.bignums.overrideAttrs (o:
if bn == "release" then {} else
if bn == "master" then { src = fetchTarball https://github.com/coq/bignums/archive/master.tar.gz; } else
@@ -28,9 +34,17 @@ let math-classes =
src = fetchTarball "https://github.com/coq-community/math-classes/archive/master.tar.gz";
}); in
-let unicoq = callPackage ./unicoq.nix { inherit coq; }; in
+let corn = (coqPackages.corn.override { inherit coq bignums math-classes; })
+ .overrideAttrs (o: {
+ src = fetchTarball "https://github.com/coq-community/corn/archive/master.tar.gz";
+ }); in
+
+let unicoq = callPackage ./unicoq { inherit coq; }; in
-let callPackage = newScope { inherit coq mathcomp bignums coqprime math-classes unicoq; }; in
+let callPackage = newScope { inherit coq
+ bignums coq-ext-lib coqprime corn math-classes
+ mathcomp simple-io ssreflect unicoq;
+}; in
# Environments for building CI libraries with this Coq
let projects = {
@@ -45,12 +59,14 @@ let projects = {
fiat_crypto = callPackage ./fiat_crypto.nix {};
fiat_crypto_legacy = callPackage ./fiat_crypto_legacy.nix {};
flocq = callPackage ./flocq.nix {};
+ formal-topology = callPackage ./formal-topology.nix {};
GeoCoq = callPackage ./GeoCoq.nix {};
HoTT = callPackage ./HoTT.nix {};
math_classes = callPackage ./math_classes.nix {};
mathcomp = {};
mtac2 = callPackage ./mtac2.nix {};
oddorder = callPackage ./oddorder.nix {};
+ quickchick = callPackage ./quickchick.nix {};
VST = callPackage ./VST.nix {};
}; in
@@ -60,10 +76,16 @@ else
let prj = projects."${project}"; in
+let inherit (stdenv.lib) optional optionals; in
+
stdenv.mkDerivation {
name = "shell-for-${project}-in-${branch}";
- buildInputs = [ coq ] ++ (prj.buildInputs or []);
+ buildInputs =
+ optional withCoq coq
+ ++ (prj.buildInputs or [])
+ ++ optionals withCoq (prj.coqBuildInputs or [])
+ ;
configure = prj.configure or "true";
make = prj.make or "make";
diff --git a/dev/ci/nix/fiat_crypto.nix b/dev/ci/nix/fiat_crypto.nix
index 7b37e6e8e4..0f0ee91387 100644
--- a/dev/ci/nix/fiat_crypto.nix
+++ b/dev/ci/nix/fiat_crypto.nix
@@ -1,6 +1,6 @@
{ coqprime }:
{
- buildInputs = [ coqprime ];
+ coqBuildInputs = [ coqprime ];
configure = "git submodule update --init --recursive && ulimit -s 32768";
make = "make new-pipeline c-files";
}
diff --git a/dev/ci/nix/formal-topology.nix b/dev/ci/nix/formal-topology.nix
new file mode 100644
index 0000000000..53b9b1182b
--- /dev/null
+++ b/dev/ci/nix/formal-topology.nix
@@ -0,0 +1,4 @@
+{ corn }:
+{
+ coqBuildInputs = [ corn ];
+}
diff --git a/dev/ci/nix/math_classes.nix b/dev/ci/nix/math_classes.nix
index b0fa2fe795..8edc3c8358 100644
--- a/dev/ci/nix/math_classes.nix
+++ b/dev/ci/nix/math_classes.nix
@@ -1,6 +1,6 @@
{ bignums }:
{
- buildInputs = [ bignums ];
+ coqBuildInputs = [ bignums ];
configure = "./configure.sh";
}
diff --git a/dev/ci/nix/mtac2.nix b/dev/ci/nix/mtac2.nix
index 9a2353c5cf..4acc326c02 100644
--- a/dev/ci/nix/mtac2.nix
+++ b/dev/ci/nix/mtac2.nix
@@ -1,5 +1,6 @@
{ coq, unicoq }:
{
- buildInputs = [ unicoq ] ++ (with coq.ocamlPackages; [ ocaml findlib camlp5 ]);
+ buildInputs = with coq.ocamlPackages; [ ocaml findlib camlp5 ];
+ coqBuildInputs = [ unicoq ];
configure = "./configure.sh";
}
diff --git a/dev/ci/nix/oddorder.nix b/dev/ci/nix/oddorder.nix
index 3b8fdbab51..2341bb3173 100644
--- a/dev/ci/nix/oddorder.nix
+++ b/dev/ci/nix/oddorder.nix
@@ -1,4 +1,4 @@
{ mathcomp }:
{
- buildInputs = [ mathcomp ];
+ coqBuildInputs = [ mathcomp ];
}
diff --git a/dev/ci/nix/quickchick.nix b/dev/ci/nix/quickchick.nix
new file mode 100644
index 0000000000..46bf02ae3c
--- /dev/null
+++ b/dev/ci/nix/quickchick.nix
@@ -0,0 +1,5 @@
+{ ocamlPackages, ssreflect, coq-ext-lib, simple-io }:
+{
+ buildInputs = with ocamlPackages; [ ocaml findlib ocamlbuild num ];
+ coqBuildInputs = [ ssreflect coq-ext-lib simple-io ];
+}
diff --git a/dev/ci/nix/shell b/dev/ci/nix/shell
index 2e4462ed40..a5f8ee8f54 100755
--- a/dev/ci/nix/shell
+++ b/dev/ci/nix/shell
@@ -17,4 +17,10 @@ else
BN=""
fi
-nix-shell ./dev/ci/nix/ --show-trace --argstr wd $PWD --argstr branch $BRANCH $PROJECT $BN
+if [ "$NOCOQ" ]; then
+ NOCOQ="--arg withCoq false"
+else
+ NOCOQ=""
+fi
+
+nix-shell ./dev/ci/nix/ --show-trace --argstr wd $PWD --argstr branch $BRANCH $PROJECT $BN $NOCOQ
diff --git a/dev/ci/nix/unicoq/META b/dev/ci/nix/unicoq/META
new file mode 100644
index 0000000000..30dd8b5559
--- /dev/null
+++ b/dev/ci/nix/unicoq/META
@@ -0,0 +1,2 @@
+archive(native) = "unicoq.cmxa"
+plugin(native) = "unicoq.cmxs"
diff --git a/dev/ci/nix/unicoq.nix b/dev/ci/nix/unicoq/default.nix
index 093c262cde..36f40dbe33 100644
--- a/dev/ci/nix/unicoq.nix
+++ b/dev/ci/nix/unicoq/default.nix
@@ -4,8 +4,16 @@ stdenv.mkDerivation {
name = "coq${coq.coq-version}-unicoq-0.0-git";
src = fetchTarball https://github.com/unicoq/unicoq/archive/master.tar.gz;
+ patches = [ ./unicoq-num.patch ];
+
buildInputs = [ coq ] ++ (with coq.ocamlPackages; [ ocaml findlib camlp5 num ]);
configurePhase = "coq_makefile -f Make -o Makefile";
installFlags = [ "COQLIB=$(out)/lib/coq/${coq.coq-version}/" ];
+
+ postInstall = ''
+ install -d $OCAMLFIND_DESTDIR
+ ln -s $out/lib/coq/${coq.coq-version}/user-contrib/Unicoq $OCAMLFIND_DESTDIR/
+ install -m 0644 ${./META} src/unicoq.a $OCAMLFIND_DESTDIR/Unicoq
+ '';
}
diff --git a/dev/ci/nix/unicoq/unicoq-num.patch b/dev/ci/nix/unicoq/unicoq-num.patch
new file mode 100644
index 0000000000..6d96d94dfc
--- /dev/null
+++ b/dev/ci/nix/unicoq/unicoq-num.patch
@@ -0,0 +1,44 @@
+commit f29bc64ee3d8b36758d17e1f5d50812e0c93063b
+Author: Vincent Laporte <Vincent.Laporte@fondation-inria.fr>
+Date: Thu Nov 29 08:59:22 2018 +0000
+
+ Make explicit dependency to num
+
+diff --git a/Make b/Make
+index 550dc6a..8aa1309 100644
+--- a/Make
++++ b/Make
+@@ -9,7 +9,7 @@ src/logger.ml
+ src/munify.mli
+ src/munify.ml
+ src/unitactics.mlg
+-src/unicoq.mllib
++src/unicoq.mlpack
+ theories/Unicoq.v
+ test-suite/munifytest.v
+ test-suite/microtests.v
+diff --git a/Makefile.local b/Makefile.local
+new file mode 100644
+index 0000000..88be365
+--- /dev/null
++++ b/Makefile.local
+@@ -0,0 +1 @@
++CAMLPKGS += -package num
+diff --git a/src/unicoq.mllib b/src/unicoq.mllib
+deleted file mode 100644
+index 2b84e2d..0000000
+--- a/src/unicoq.mllib
++++ /dev/null
+@@ -1,3 +0,0 @@
+-Logger
+-Munify
+-Unitactics
+diff --git a/src/unicoq.mlpack b/src/unicoq.mlpack
+new file mode 100644
+index 0000000..2b84e2d
+--- /dev/null
++++ b/src/unicoq.mlpack
+@@ -0,0 +1,3 @@
++Logger
++Munify
++Unitactics
diff --git a/dev/ci/user-overlays/06914-maximedenes-primitive-integers.sh b/dev/ci/user-overlays/06914-maximedenes-primitive-integers.sh
new file mode 100644
index 0000000000..6e89741e29
--- /dev/null
+++ b/dev/ci/user-overlays/06914-maximedenes-primitive-integers.sh
@@ -0,0 +1,9 @@
+if [ "$CI_PULL_REQUEST" = "6914" ] || [ "$CI_BRANCH" = "primitive-bool-list" ]; then
+
+ bignums_CI_REF=primitive-integers
+ bignums_CI_GITURL=https://github.com/vbgl/bignums
+
+ mtac2_CI_REF=primitive-integers
+ mtac2_CI_GITURL=https://github.com/vbgl/Mtac2
+
+fi
diff --git a/dev/ci/user-overlays/09263-maximedenes-parsing-state.sh b/dev/ci/user-overlays/09263-maximedenes-parsing-state.sh
new file mode 100644
index 0000000000..ebd1b524da
--- /dev/null
+++ b/dev/ci/user-overlays/09263-maximedenes-parsing-state.sh
@@ -0,0 +1,12 @@
+if [ "$CI_PULL_REQUEST" = "9263" ] || [ "$CI_BRANCH" = "parsing-state" ]; then
+
+ mtac2_CI_REF=proof-mode
+ mtac2_CI_GITURL=https://github.com/maximedenes/Mtac2
+
+ ltac2_CI_REF=proof-mode
+ ltac2_CI_GITURL=https://github.com/maximedenes/ltac2
+
+ equations_CI_REF=proof-mode
+ equations_CI_GITURL=https://github.com/maximedenes/Coq-Equations
+
+fi
diff --git a/dev/doc/MERGING.md b/dev/doc/MERGING.md
index 56fdab0c26..5705857d76 100644
--- a/dev/doc/MERGING.md
+++ b/dev/doc/MERGING.md
@@ -93,7 +93,7 @@ put the approriate label. Otherwise, they are expected to merge the PR using the
When CI has a few failures which look spurious, restarting the corresponding
jobs is a good way of ensuring this was indeed the case.
-To restart a job on Travis or on AppVeyor, you should connect using your GitHub
+To restart a job on AppVeyor, you should connect using your GitHub
account; being part of the Coq organization on GitHub should give you the
permission to do so.
To restart a job on GitLab CI, you should sign into GitLab (this can be done
diff --git a/dev/doc/profiling.txt b/dev/doc/profiling.txt
index 29e87df6b8..8455d13377 100644
--- a/dev/doc/profiling.txt
+++ b/dev/doc/profiling.txt
@@ -10,7 +10,7 @@ In Coq source folder:
opam switch 4.05.0+trunk+fp
./configure -local -debug
make
-perf record -g bin/coqtop -compile file.v
+perf record -g bin/coqc file.v
perf report -g fractal,callee --no-children
To profile only part of a file, first load it using
@@ -96,7 +96,7 @@ https://github.com/mshinwell/opam-repo-dev
### For memory dump:
-CAMLRUNPARAM=T,mj bin/coqtop -compile file.v
+CAMLRUNPARAM=T,mj bin/coqc file.v
In another terminal:
@@ -112,7 +112,7 @@ number of objects and third is the place where the objects where allocated.
### For complete memory graph:
-CAMLRUNPARAM=T,gr bin/coqtop -compile file.v
+CAMLRUNPARAM=T,gr bin/coqc file.v
In another terminal:
diff --git a/dev/doc/release-process.md b/dev/doc/release-process.md
index b1c111685b..d05b6c8eef 100644
--- a/dev/doc/release-process.md
+++ b/dev/doc/release-process.md
@@ -4,37 +4,20 @@
- [ ] Create a new issue to track the release process where you can copy-paste
the present checklist.
-- [ ] Change the version name to the next major version and the magic numbers
- (see [#7008](https://github.com/coq/coq/pull/7008/files)).
-- [ ] Update the compatibility infrastructure, which consists of doing
- the following steps. Note that all but the final step can be
- performed automatically by
- [`dev/tools/update-compat.py`](/dev/tools/update-compat.py) so
- long as you have already updated `coq_version` in
- [`configure.ml`](/configure.ml).
- + [ ] Add a file `theories/Compat/CoqXX.v` which contains just the header
- from [`dev/header.ml`](/dev/header.ml)
- + [ ] Add the line `Require Export Coq.Compat.CoqXX.` at the top of
- `theories/Compat/CoqYY.v`, where Y.Y is the version prior to X.X.
- + [ ] Delete the file `theories/Compat/CoqWW.v`, where W.W is three versions
- prior to X.X.
- + [ ] Update
- [`doc/stdlib/index-list.html.template`](/doc/stdlib/index-list.html.template)
- with the deleted/added files.
- + [ ] Remove any notations in the standard library which have `compat "W.W"`.
- + [ ] Update the type `compat_version` in [`lib/flags.ml`](/lib/flags.ml) by
- bumping all the version numbers by one, and update the interpretations
- of those flags in [`toplevel/coqargs.ml`](/toplevel/coqargs.ml) and
- [`vernac/g_vernac.mlg`](/vernac/g_vernac.mlg).
- + [ ] Update the files
- [`test-suite/success/CompatCurrentFlag.v`](/test-suite/success/CompatCurrentFlag.v),
- [`test-suite/success/CompatPreviousFlag.v`](/test-suite/success/CompatPreviousFlag.v),
- and
- [`test-suite/success/CompatOldFlag.v`](/test-suite/success/CompatOldFlag.v)
- by bumping all version numbers by 1.
- + [ ] Decide what to do about all test-suite files which mention `-compat
- W.W` or `Coq.Comapt.CoqWW` (which is no longer valid, since we only
- keep compatibility against the two previous versions)
+- [ ] Change the version name to the next major version and the magic
+ numbers (see [#7008](https://github.com/coq/coq/pull/7008/files)).
+
+ Additionally, in the same commit, update the compatibility
+ infrastructure, which consists of invoking
+ [`dev/tools/update-compat.py`](../tools/update-compat.py) with the
+ `--master` flag.
+
+ Note that the `update-compat.py` script must be run twice: once
+ *immediately after* branching with the `--master` flag (which sets
+ up Coq to support four `-compat` flag arguments), *in the same
+ commit* as the one that updates `coq_version` in
+ [`configure.ml`](../../configure.ml), and once again later on before
+ the next branch point with the `--release` flag (see next section).
- [ ] Put the corresponding alpha tag using `git tag -s`.
The `VX.X+alpha` tag marks the first commit to be in `master` and not in the
branch of the previous version.
@@ -43,6 +26,19 @@
release date) and put this information in the milestone (using the
description and due date fields).
+## Anytime after the previous version is branched off master ##
+
+- [ ] Update the compatibility infrastructure to the next release,
+ which consists of invoking
+ [`dev/tools/update-compat.py`](../tools/update-compat.py) with the
+ `--release` flag; this sets up Coq to support three `-compat` flag
+ arguments. To ensure that CI passes, you will have to decide what
+ to do about all test-suite files which mention `-compat U.U` or
+ `Coq.Comapt.CoqUU` (which is no longer valid, since we only keep
+ compatibility against the two previous versions on releases), and
+ you may have to prepare overlays for projects using the
+ compatibility flags.
+
## About one month before the beta ##
- [ ] Create the `X.X.0` milestone and set its due date.
diff --git a/dev/doc/versions-history.tex b/dev/doc/versions-history.tex
index 8f9c3171da..1c4913d201 100644
--- a/dev/doc/versions-history.tex
+++ b/dev/doc/versions-history.tex
@@ -271,7 +271,7 @@ Coq ``V7'' archive & August 1999 & new cvs archive based on J.-C. Filliâtre's \
& & \feature{kernel-centric} architecture \\
& & more care for outside readers\\
& & (indentation, ocaml warning protection)\\
-Coq V7.0beta& released 27 December 2000 & \feature{${\cal L}_{\mathit{tac}}$} \\
+Coq V7.0beta& released 27 December 2000 & \feature{${\mathcal{L}}_{\mathit{tac}}$} \\
Coq V7.0beta2& released 2 February 2001\\
Coq V7.0& released 25 April 2001 & \feature{extraction} (version 2) [6-2-2001] \\
diff --git a/dev/tools/merge-pr.sh b/dev/tools/merge-pr.sh
index a27dacc5a7..813ad71be9 100755
--- a/dev/tools/merge-pr.sh
+++ b/dev/tools/merge-pr.sh
@@ -143,7 +143,7 @@ fi
# Sanity check: PR has an outdated version of CI
BASE_COMMIT=$(echo "$PRDATA" | jq -r '.base.sha')
-CI_FILES=(".travis.yml" ".gitlab-ci.yml" "appveyor.yml")
+CI_FILES=(".gitlab-ci.yml" "azure-pipelines.yml")
if ! git diff --quiet "$BASE_COMMIT" "$LOCAL_BRANCH_COMMIT" -- "${CI_FILES[@]}"
then
diff --git a/dev/tools/update-compat.py b/dev/tools/update-compat.py
index 14094553a2..ff9b32fe78 100755
--- a/dev/tools/update-compat.py
+++ b/dev/tools/update-compat.py
@@ -1,6 +1,60 @@
#!/usr/bin/env python
from __future__ import with_statement
-import os, re, sys
+import os, re, sys, subprocess
+
+# When passed `--release`, this script sets up Coq to support three
+# `-compat` flag arguments. If executed manually, this would consist
+# of doing the following steps:
+#
+# - Delete the file `theories/Compat/CoqUU.v`, where U.U is four
+# versions prior to the new version X.X. After this, there
+# should be exactly three `theories/Compat/CoqNN.v` files.
+# - Update
+# [`doc/stdlib/index-list.html.template`](/doc/stdlib/index-list.html.template)
+# with the deleted file.
+# - Remove any notations in the standard library which have `compat "U.U"`.
+# - Update the type `compat_version` in [`lib/flags.ml`](/lib/flags.ml) by
+# bumping all the version numbers by one, and update the interpretations
+# of those flags in [`toplevel/coqargs.ml`](/toplevel/coqargs.ml) and
+# [`vernac/g_vernac.mlg`](/vernac/g_vernac.mlg).
+#
+# - Remove the file
+# [`test-suite/success/CompatOldOldFlag.v`](/test-suite/success/CompatOldOldFlag.v).
+# - Update
+# [`test-suite/tools/update-compat/run.sh`](/test-suite/tools/update-compat/run.sh)
+# to ensure that it passes `--release` to the `update-compat.py`
+# script.
+
+# When passed the `--master` flag, this script sets up Coq to support
+# four `-compat` flag arguments. If executed manually, this would
+# consist of doing the following steps:
+#
+# - Add a file `theories/Compat/CoqXX.v` which contains just the header
+# from [`dev/header.ml`](/dev/header.ml)
+# - Add the line `Require Export Coq.Compat.CoqXX.` at the top of
+# `theories/Compat/CoqYY.v`, where Y.Y is the version prior to X.X.
+# - Update
+# [`doc/stdlib/index-list.html.template`](/doc/stdlib/index-list.html.template)
+# with the added file.
+# - Update the type `compat_version` in [`lib/flags.ml`](/lib/flags.ml) by
+# bumping all the version numbers by one, and update the interpretations
+# of those flags in [`toplevel/coqargs.ml`](/toplevel/coqargs.ml) and
+# [`vernac/g_vernac.mlg`](/vernac/g_vernac.mlg).
+# - Update the files
+# [`test-suite/success/CompatCurrentFlag.v`](/test-suite/success/CompatCurrentFlag.v),
+# [`test-suite/success/CompatPreviousFlag.v`](/test-suite/success/CompatPreviousFlag.v),
+# and
+# [`test-suite/success/CompatOldFlag.v`](/test-suite/success/CompatOldFlag.v)
+# by bumping all version numbers by 1. Re-create the file
+# [`test-suite/success/CompatOldOldFlag.v`](/test-suite/success/CompatOldOldFlag.v)
+# with its version numbers also bumped by 1 (file should have
+# been removed before branching; see above).
+# - Update
+# [`test-suite/tools/update-compat/run.sh`](/test-suite/tools/update-compat/run.sh)
+# to ensure that it passes `--master` to the `update-compat.py`
+# script.
+
+
# Obtain the absolute path of the script being run. By assuming that
# the script lives in dev/tools/, and basing all calls on the path of
@@ -11,6 +65,8 @@ ROOT_PATH = os.path.realpath(os.path.join(SCRIPT_PATH, '..', '..'))
CONFIGURE_PATH = os.path.join(ROOT_PATH, 'configure.ml')
HEADER_PATH = os.path.join(ROOT_PATH, 'dev', 'header.ml')
DEFAULT_NUMBER_OF_OLD_VERSIONS = 2
+RELEASE_NUMBER_OF_OLD_VERSIONS = 2
+MASTER_NUMBER_OF_OLD_VERSIONS = 3
EXTRA_HEADER = '\n(** Compatibility file for making Coq act similar to Coq v%s *)\n'
FLAGS_MLI_PATH = os.path.join(ROOT_PATH, 'lib', 'flags.mli')
FLAGS_ML_PATH = os.path.join(ROOT_PATH, 'lib', 'flags.ml')
@@ -18,18 +74,46 @@ COQARGS_ML_PATH = os.path.join(ROOT_PATH, 'toplevel', 'coqargs.ml')
G_VERNAC_PATH = os.path.join(ROOT_PATH, 'vernac', 'g_vernac.mlg')
DOC_INDEX_PATH = os.path.join(ROOT_PATH, 'doc', 'stdlib', 'index-list.html.template')
BUG_4798_PATH = os.path.join(ROOT_PATH, 'test-suite', 'bugs', 'closed', 'bug_4798.v')
+BUG_9166_PATH = os.path.join(ROOT_PATH, 'test-suite', 'bugs', 'closed', 'bug_9166.v')
+TEST_SUITE_RUN_PATH = os.path.join(ROOT_PATH, 'test-suite', 'tools', 'update-compat', 'run.sh')
TEST_SUITE_PATHS = tuple(os.path.join(ROOT_PATH, 'test-suite', 'success', i)
for i in ('CompatOldOldFlag.v', 'CompatOldFlag.v', 'CompatPreviousFlag.v', 'CompatCurrentFlag.v'))
TEST_SUITE_DESCRIPTIONS = ('current-minus-three', 'current-minus-two', 'current-minus-one', 'current')
# sanity check that we are where we think we are
assert(os.path.normpath(os.path.realpath(SCRIPT_PATH)) == os.path.normpath(os.path.realpath(os.path.join(ROOT_PATH, 'dev', 'tools'))))
assert(os.path.exists(CONFIGURE_PATH))
+BUG_HEADER = r"""(* DO NOT MODIFY THIS FILE DIRECTLY *)
+(* It is autogenerated by %s. *)
+""" % os.path.relpath(os.path.realpath(__file__), ROOT_PATH)
def get_header():
with open(HEADER_PATH, 'r') as f: return f.read()
HEADER = get_header()
+def break_or_continue():
+ msg = 'Press ENTER to continue, or Ctrl+C to break...'
+ try:
+ raw_input(msg)
+ except NameError: # we must be running python3
+ input(msg)
+
+def maybe_git_add(local_path, suggest_add=True, **args):
+ if args['git_add']:
+ print("Running 'git add %s'..." % local_path)
+ retc = subprocess.call(['git', 'add', local_path], cwd=ROOT_PATH)
+ if retc is not None and retc != 0:
+ print('!!! Process returned code %d' % retc)
+ elif suggest_add:
+ print(r"!!! Don't forget to 'git add %s'!" % local_path)
+
+def maybe_git_rm(local_path, **args):
+ if args['git_add']:
+ print("Running 'git rm %s'..." % local_path)
+ retc = subprocess.call(['git', 'rm', local_path], cwd=ROOT_PATH)
+ if retc is not None and retc != 0:
+ print('!!! Process returned code %d' % retc)
+
def get_version(cur_version=None):
if cur_version is not None: return cur_version
with open(CONFIGURE_PATH, 'r') as f:
@@ -72,11 +156,56 @@ def get_known_versions():
def get_new_versions(known_versions, **args):
if args['cur_version'] in known_versions:
assert(known_versions[-1] == args['cur_version'])
- assert(len(known_versions) == args['number_of_compat_versions'])
- return known_versions
+ known_versions = known_versions[:-1]
assert(len(known_versions) >= args['number_of_old_versions'])
return tuple(list(known_versions[-args['number_of_old_versions']:]) + [args['cur_version']])
+def print_diff(olds, news, numch=30):
+ for ch in range(min(len(olds), len(news))):
+ if olds[ch] != news[ch]:
+ print('Character %d differs:\nOld: %s\nNew: %s' % (ch, repr(olds[ch:][:numch]), repr(news[ch:][numch])))
+ return
+ ch = min(len(olds), len(news))
+ assert(len(olds) != len(news))
+ print('Strings are different lengths:\nOld tail: %s\nNew tail: %s' % (repr(olds[ch:]), repr(news[ch:])))
+
+def update_shebang_to_match(contents, new_contents, path):
+ contents_lines = contents.split('\n')
+ new_contents_lines = new_contents.split('\n')
+ if not (contents_lines[0].startswith('#!/') and contents_lines[0].endswith('bash')):
+ raise Exception('Unrecognized #! line in existing %s: %s' % (os.path.relpath(path, ROOT_PATH), repr(contents_lines[0])))
+ if not (new_contents_lines[0].startswith('#!/') and new_contents_lines[0].endswith('bash')):
+ raise Exception('Unrecognized #! line in new %s: %s' % (os.path.relpath(path, ROOT_PATH), repr(new_contents_lines[0])))
+ new_contents_lines[0] = contents_lines[0]
+ return '\n'.join(new_contents_lines)
+
+def update_if_changed(contents, new_contents, path, exn_string='%s changed!', suggest_add=False, pass_through_shebang=False, assert_unchanged=False, **args):
+ if contents is not None and pass_through_shebang:
+ new_contents = update_shebang_to_match(contents, new_contents, path)
+ if contents is None or contents != new_contents:
+ if not assert_unchanged:
+ print('Updating %s...' % os.path.relpath(path, ROOT_PATH))
+ with open(path, 'w') as f:
+ f.write(new_contents)
+ maybe_git_add(os.path.relpath(path, ROOT_PATH), suggest_add=suggest_add, **args)
+ else:
+ if contents is not None:
+ print('Unexpected change:\nOld contents:\n%s\n\nNew contents:\n%s\n' % (contents, new_contents))
+ print_diff(contents, new_contents)
+ raise Exception(exn_string % os.path.relpath(path, ROOT_PATH))
+
+def remove_if_exists(path, exn_string='%s exists when it should not!', assert_unchanged=False, **args):
+ if os.path.exists(path):
+ if not assert_unchanged:
+ print('Removing %s...' % os.path.relpath(path, ROOT_PATH))
+ os.remove(path)
+ maybe_git_rm(os.path.relpath(path, ROOT_PATH), **args)
+ else:
+ raise Exception(exn_string % os.path.relpath(path, ROOT_PATH))
+
+def update_file(new_contents, path, **args):
+ update_if_changed(None, new_contents, path, **args)
+
def update_compat_files(old_versions, new_versions, assert_unchanged=False, **args):
for v in old_versions:
if v not in new_versions:
@@ -85,6 +214,7 @@ def update_compat_files(old_versions, new_versions, assert_unchanged=False, **ar
print('Removing %s...' % compat_file)
compat_path = os.path.join(ROOT_PATH, compat_file)
os.rename(compat_path, compat_path + '.bak')
+ maybe_git_rm(compat_file, **args)
else:
raise Exception('%s exists!' % compat_file)
for v, next_v in zip(new_versions, list(new_versions[1:]) + [None]):
@@ -95,12 +225,7 @@ def update_compat_files(old_versions, new_versions, assert_unchanged=False, **ar
contents = HEADER + (EXTRA_HEADER % v)
if next_v is not None:
contents += '\nRequire Export Coq.Compat.%s.\n' % version_name_to_compat_name(next_v, ext='')
- if not assert_unchanged:
- with open(compat_path, 'w') as f:
- f.write(contents)
- print(r"Don't forget to 'git add %s'!" % compat_file)
- else:
- raise Exception('%s does not exist!' % compat_file)
+ update_file(contents, compat_path, exn_string='%s does not exist!', assert_unchanged=assert_unchanged, **args)
else:
# print('Checking %s...' % compat_file)
with open(compat_path, 'r') as f:
@@ -116,12 +241,7 @@ def update_compat_files(old_versions, new_versions, assert_unchanged=False, **ar
if not contents.startswith(header + '\n'):
contents = contents.replace(header, header + '\n')
contents = contents.replace(header, '%s\n%s' % (header, line))
- if not assert_unchanged:
- print('Updating %s...' % compat_file)
- with open(compat_path, 'w') as f:
- f.write(contents)
- else:
- raise Exception('Compat file %s is missing line %s' % (compat_file, line))
+ update_file(contents, compat_path, exn_string=('Compat file %%s is missing line %s' % line), assert_unchanged=assert_unchanged, **args)
def update_compat_versions_type_line(new_versions, contents, relpath):
compat_version_string = ' | '.join(['V%s_%s' % tuple(v.split('.')) for v in new_versions[:-1]] + ['Current'])
@@ -173,11 +293,18 @@ def update_add_compat_require(new_versions, contents, relpath):
return new_contents
def update_parse_compat_version(new_versions, contents, relpath, **args):
- line_count = args['number_of_compat_versions']+2 # 1 for the first line, 1 for the invalid flags
+ line_count = 3 # 1 for the first line, 1 for the invalid flags, and 1 for Current
first_line = 'let parse_compat_version = let open Flags in function'
- old_function_lines = contents[contents.index(first_line):].split('\n')[:line_count]
- if re.match(r'^ \| \([0-9 "\.\|]*\) as s ->$', old_function_lines[-1]) is None:
- raise Exception('Could not recognize line %d of parse_compat_version in %s as a list of invalid versions' % (line_count, relpath))
+ split_contents = contents[contents.index(first_line):].split('\n')
+ while True:
+ cur_line = split_contents[:line_count][-1]
+ if re.match(r'^ \| \([0-9 "\.\|]*\) as s ->$', cur_line) is not None:
+ break
+ elif re.match(r'^ \| "[0-9\.]*" -> V[0-9_]*$', cur_line) is not None:
+ line_count += 1
+ else:
+ raise Exception('Could not recognize line %d of parse_compat_version in %s as a list of invalid versions (line was %s)' % (line_count, relpath, repr(cur_line)))
+ old_function_lines = split_contents[:line_count]
all_versions = re.findall(r'"([0-9\.]+)"', ''.join(old_function_lines))
invalid_versions = tuple(i for i in all_versions if i not in new_versions)
new_function_lines = [first_line]
@@ -197,15 +324,6 @@ def check_no_old_versions(old_versions, new_versions, contents, relpath):
if V in contents:
raise Exception('Unreplaced usage of %s remaining in %s' % (V, relpath))
-def update_if_changed(contents, new_contents, path, assert_unchanged=False, **args):
- if contents != new_contents:
- if not assert_unchanged:
- print('Updating %s...' % os.path.relpath(path, ROOT_PATH))
- with open(path, 'w') as f:
- f.write(new_contents)
- else:
- raise Exception('%s changed!' % os.path.relpath(path, ROOT_PATH))
-
def update_flags_mli(old_versions, new_versions, **args):
with open(FLAGS_MLI_PATH, 'r') as f: contents = f.read()
new_contents = update_compat_versions_type_line(new_versions, contents, os.path.relpath(FLAGS_MLI_PATH, ROOT_PATH))
@@ -238,21 +356,26 @@ def update_flags(old_versions, new_versions, **args):
update_coqargs_ml(old_versions, new_versions, **args)
update_g_vernac(old_versions, new_versions, **args)
-def update_test_suite(new_versions, assert_unchanged=False, test_suite_paths=TEST_SUITE_PATHS, test_suite_descriptions=TEST_SUITE_DESCRIPTIONS, **args):
+def update_test_suite(new_versions, assert_unchanged=False, test_suite_paths=TEST_SUITE_PATHS, test_suite_descriptions=TEST_SUITE_DESCRIPTIONS, test_suite_outdated_paths=tuple(), **args):
assert(len(new_versions) == len(test_suite_paths))
assert(len(new_versions) == len(test_suite_descriptions))
for i, (v, path, descr) in enumerate(zip(new_versions, test_suite_paths, test_suite_descriptions)):
- if not os.path.exists(path):
- raise Exception('Could not find existing file %s' % os.path.relpath(path, ROOT_PATH))
+ contents = None
+ suggest_add = False
+ if os.path.exists(path):
+ with open(path, 'r') as f: contents = f.read()
+ else:
+ suggest_add = True
if '%s' in descr: descr = descr % v
- with open(path, 'r') as f: contents = f.read()
lines = ['(* -*- coq-prog-args: ("-compat" "%s") -*- *)' % v,
'(** Check that the %s compatibility flag actually requires the relevant modules. *)' % descr]
for imp_v in reversed(new_versions[i:]):
lines.append('Import Coq.Compat.%s.' % version_name_to_compat_name(imp_v, ext=''))
lines.append('')
new_contents = '\n'.join(lines)
- update_if_changed(contents, new_contents, path, **args)
+ update_if_changed(contents, new_contents, path, suggest_add=suggest_add, **args)
+ for path in test_suite_outdated_paths:
+ remove_if_exists(path, assert_unchanged=assert_unchanged, **args)
def update_doc_index(new_versions, **args):
with open(DOC_INDEX_PATH, 'r') as f: contents = f.read()
@@ -264,17 +387,48 @@ def update_doc_index(new_versions, **args):
new_contents = new_contents.replace(firstline, '\n'.join([firstline] + extra_lines))
update_if_changed(contents, new_contents, DOC_INDEX_PATH, **args)
+def update_test_suite_run(**args):
+ with open(TEST_SUITE_RUN_PATH, 'r') as f: contents = f.read()
+ new_contents = r'''#!/usr/bin/env bash
+
+# allow running this script from any directory by basing things on where the script lives
+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 %s || exit $?
+''' % ' '.join([('--master' if args['master'] else ''), ('--release' if args['release'] else '')]).strip()
+ update_if_changed(contents, new_contents, TEST_SUITE_RUN_PATH, pass_through_shebang=True, **args)
+
def update_bug_4789(new_versions, **args):
# we always update this compat notation to oldest
# currently-supported compat version, which should never be the
# current version
with open(BUG_4798_PATH, 'r') as f: contents = f.read()
- new_contents = r"""Check match 2 with 0 => 0 | S n => n end.
+ new_contents = BUG_HEADER + r"""Check match 2 with 0 => 0 | S n => n end.
Notation "|" := 1 (compat "%s").
Check match 2 with 0 => 0 | S n => n end. (* fails *)
""" % new_versions[0]
update_if_changed(contents, new_contents, BUG_4798_PATH, **args)
+def update_bug_9166(new_versions, **args):
+ # we always update this compat notation to oldest
+ # currently-supported compat version, which should never be the
+ # current version
+ with open(BUG_9166_PATH, 'r') as f: contents = f.read()
+ new_contents = BUG_HEADER + r"""Set Warnings "+deprecated".
+
+Notation bar := option (compat "%s").
+
+Definition foo (x: nat) : nat :=
+ match x with
+ | 0 => 0
+ | S bar => bar
+ end.
+""" % new_versions[0]
+ update_if_changed(contents, new_contents, BUG_9166_PATH, **args)
+
def update_compat_notations_in(old_versions, new_versions, contents):
for v in old_versions:
if v not in new_versions:
@@ -305,11 +459,26 @@ def parse_args(argv):
args = {
'assert_unchanged': False,
'cur_version': None,
- 'number_of_old_versions': DEFAULT_NUMBER_OF_OLD_VERSIONS
+ 'number_of_old_versions': None,
+ 'master': False,
+ 'release': False,
+ 'git_add': False,
}
+ if '--master' not in argv and '--release' not in argv:
+ print(r'''WARNING: You should pass either --release (sometime before branching)
+ or --master (right after branching and updating the version number in version.ml)''')
+ if '--assert-unchanged' not in args: break_or_continue()
for arg in argv[1:]:
if arg == '--assert-unchanged':
args['assert_unchanged'] = True
+ elif arg == '--git-add':
+ args['git_add'] = True
+ elif arg == '--master':
+ args['master'] = True
+ if args['number_of_old_versions'] is None: args['number_of_old_versions'] = MASTER_NUMBER_OF_OLD_VERSIONS
+ elif arg == '--release':
+ args['release'] = True
+ if args['number_of_old_versions'] is None: args['number_of_old_versions'] = RELEASE_NUMBER_OF_OLD_VERSIONS
elif arg.startswith('--cur-version='):
args['cur_version'] = arg[len('--cur-version='):]
assert(len(args['cur_version'].split('.')) == 2)
@@ -317,10 +486,11 @@ def parse_args(argv):
elif arg.startswith('--number-of-old-versions='):
args['number_of_old_versions'] = int(arg[len('--number-of-old-versions='):])
else:
- print('USAGE: %s [--assert-unchanged] [--cur-version=NN.NN] [--number-of-old-versions=NN]' % argv[0])
+ print('USAGE: %s [--assert-unchanged] [--cur-version=NN.NN] [--number-of-old-versions=NN] [--git-add]' % argv[0])
print('')
print('ERROR: Unrecognized argument: %s' % arg)
sys.exit(1)
+ if args['number_of_old_versions'] is None: args['number_of_old_versions'] = DEFAULT_NUMBER_OF_OLD_VERSIONS
return args
if __name__ == '__main__':
@@ -331,11 +501,14 @@ if __name__ == '__main__':
new_versions = get_new_versions(known_versions, **args)
assert(len(TEST_SUITE_PATHS) >= args['number_of_compat_versions'])
args['test_suite_paths'] = tuple(TEST_SUITE_PATHS[-args['number_of_compat_versions']:])
+ args['test_suite_outdated_paths'] = tuple(TEST_SUITE_PATHS[:-args['number_of_compat_versions']])
args['test_suite_descriptions'] = tuple(TEST_SUITE_DESCRIPTIONS[-args['number_of_compat_versions']:])
update_compat_files(known_versions, new_versions, **args)
update_flags(known_versions, new_versions, **args)
update_test_suite(new_versions, **args)
+ update_test_suite_run(**args)
update_doc_index(new_versions, **args)
update_bug_4789(new_versions, **args)
+ update_bug_9166(new_versions, **args)
update_compat_notations(known_versions, new_versions, **args)
display_git_grep(known_versions, new_versions)
diff --git a/dev/top_printers.ml b/dev/top_printers.ml
index 8f207d1e0a..2629cf8626 100644
--- a/dev/top_printers.ml
+++ b/dev/top_printers.ml
@@ -292,6 +292,8 @@ let constr_display csr =
^(Array.fold_right (fun x i -> (name_display x)^(if not(i="")
then (";"^i) else "")) lna "")^","
^(array_display bl)^")"
+ | Int i ->
+ "Int("^(Uint63.to_string i)^")"
and array_display v =
"[|"^
@@ -421,6 +423,8 @@ let print_pure_constr csr =
print_cut();
done
in print_string"{"; print_fix (); print_string"}"
+ | Int i ->
+ print_string ("Int("^(Uint63.to_string i)^")")
and box_display c = open_hovbox 1; term_display c; close_box()
diff --git a/dev/vm_printers.ml b/dev/vm_printers.ml
index ea126e2756..dc30793a6e 100644
--- a/dev/vm_printers.ml
+++ b/dev/vm_printers.ml
@@ -82,6 +82,7 @@ and ppwhd whd =
| Vcofix _ -> print_string "cofix"
| Vconstr_const i -> print_string "C(";print_int i;print_string")"
| Vconstr_block b -> ppvblock b
+ | Vint64 i -> printf "int64(%LiL)" i
| Vatom_stk(a,s) ->
open_hbox();ppatom a;close_box();
print_string"@";ppstack s
diff --git a/doc/common/macros.tex b/doc/common/macros.tex
index 6a28c5b3d1..927a912fbf 100644
--- a/doc/common/macros.tex
+++ b/doc/common/macros.tex
@@ -242,7 +242,7 @@
\newcommand{\vref}{\nterm{ref}}
\newcommand{\zarithformula}{\nterm{zarith\_formula}}
\newcommand{\zarith}{\nterm{zarith}}
-\newcommand{\ltac}{\mbox{${\cal L}_{tac}$}}
+\newcommand{\ltac}{\mbox{${\mathcal{L}}_{tac}$}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \mbox{\sf } series for roman text in maths formulas %
@@ -373,15 +373,15 @@
\newcommand{\sumbool}[2]{\{#1\}+\{#2\}}
\newcommand{\myifthenelse}[3]{\kw{if} ~ #1 ~\kw{then} ~ #2 ~ \kw{else} ~ #3}
\newcommand{\fun}[2]{\item[]{\tt {#1}}. \quad\\ #2}
-\newcommand{\WF}[2]{\ensuremath{{\cal W\!F}(#1)[#2]}}
-\newcommand{\WFTWOLINES}[2]{\ensuremath{{\cal W\!F}\begin{array}{l}(#1)\\\mbox{}[{#2}]\end{array}}}
+\newcommand{\WF}[2]{\ensuremath{{\mathcal{W\!F}}(#1)[#2]}}
+\newcommand{\WFTWOLINES}[2]{\ensuremath{{\mathcal{W\!F}}\begin{array}{l}(#1)\\\mbox{}[{#2}]\end{array}}}
\newcommand{\WFE}[1]{\WF{E}{#1}}
\newcommand{\WT}[4]{\ensuremath{#1[#2] \vdash #3 : #4}}
\newcommand{\WTE}[3]{\WT{E}{#1}{#2}{#3}}
\newcommand{\WTEG}[2]{\WTE{\Gamma}{#1}{#2}}
\newcommand{\WTM}[3]{\WT{#1}{}{#2}{#3}}
-\newcommand{\WFT}[2]{\ensuremath{#1[] \vdash {\cal W\!F}(#2)}}
+\newcommand{\WFT}[2]{\ensuremath{#1[] \vdash {\mathcal{W\!F}}(#2)}}
\newcommand{\WS}[3]{\ensuremath{#1[] \vdash #2 <: #3}}
\newcommand{\WSE}[2]{\WS{E}{#1}{#2}}
\newcommand{\WEV}[3]{\mbox{$#1[] \vdash #2 \lra #3$}}
@@ -427,7 +427,7 @@
\newcommand{\letin}[3]{\kw{let}~#1:=#2~\kw{in}~#3}
\newcommand{\subst}[3]{#1\{#2/#3\}}
\newcommand{\substs}[4]{#1\{(#2/#3)_{#4}\}}
-\newcommand{\Sort}{\mbox{$\cal S$}}
+\newcommand{\Sort}{\mbox{$\mathcal{S}$}}
\newcommand{\convert}{=_{\beta\delta\iota\zeta\eta}}
\newcommand{\leconvert}{\leq_{\beta\delta\iota\zeta\eta}}
\newcommand{\NN}{\mathbb{N}}
diff --git a/doc/sphinx/README.rst b/doc/sphinx/README.rst
index a20b74822c..e4f078c1d6 100644
--- a/doc/sphinx/README.rst
+++ b/doc/sphinx/README.rst
@@ -416,12 +416,12 @@ Omitting annotations
DO
.. code::
- .. tacv:: assert @form as @intro_pattern
+ .. tacv:: assert @form as @simple_intropattern
DON'T
.. code::
- .. tacv:: assert form as intro_pattern
+ .. tacv:: assert form as simple_intropattern
Using the ``.. coqtop::`` directive for syntax highlighting
-----------------------------------------------------------
diff --git a/doc/sphinx/README.template.rst b/doc/sphinx/README.template.rst
index 11f0cdc008..81f25bf274 100644
--- a/doc/sphinx/README.template.rst
+++ b/doc/sphinx/README.template.rst
@@ -172,12 +172,12 @@ Omitting annotations
DO
.. code::
- .. tacv:: assert @form as @intro_pattern
+ .. tacv:: assert @form as @simple_intropattern
DON'T
.. code::
- .. tacv:: assert form as intro_pattern
+ .. tacv:: assert form as simple_intropattern
Using the ``.. coqtop::`` directive for syntax highlighting
-----------------------------------------------------------
diff --git a/doc/sphinx/addendum/generalized-rewriting.rst b/doc/sphinx/addendum/generalized-rewriting.rst
index e468cc63cd..b606fb4dd2 100644
--- a/doc/sphinx/addendum/generalized-rewriting.rst
+++ b/doc/sphinx/addendum/generalized-rewriting.rst
@@ -714,47 +714,47 @@ following grammar:
.. productionlist:: rewriting
s, t, u : `strategy`
- : | `lemma`
- : | `lemma_right_to_left`
- : | `failure`
- : | `identity`
- : | `reflexivity`
- : | `progress`
- : | `failure_catch`
- : | `composition`
- : | `left_biased_choice`
- : | `iteration_one_or_more`
- : | `iteration_zero_or_more`
- : | `one_subterm`
- : | `all_subterms`
- : | `innermost_first`
- : | `outermost_first`
- : | `bottom_up`
- : | `top_down`
- : | `apply_hint`
- : | `any_of_the_terms`
- : | `apply_reduction`
- : | `fold_expression`
+ : `lemma`
+ : `lemma_right_to_left`
+ : `failure`
+ : `identity`
+ : `reflexivity`
+ : `progress`
+ : `failure_catch`
+ : `composition`
+ : `left_biased_choice`
+ : `iteration_one_or_more`
+ : `iteration_zero_or_more`
+ : `one_subterm`
+ : `all_subterms`
+ : `innermost_first`
+ : `outermost_first`
+ : `bottom_up`
+ : `top_down`
+ : `apply_hint`
+ : `any_of_the_terms`
+ : `apply_reduction`
+ : `fold_expression`
.. productionlist:: rewriting
- strategy : "(" `s` ")"
+ strategy : ( `s` )
lemma : `c`
- lemma_right_to_left : "<-" `c`
- failure : `fail`
- identity : `id`
- reflexivity : `refl`
- progress : `progress` `s`
- failure_catch : `try` `s`
- composition : `s` ";" `u`
+ lemma_right_to_left : <- `c`
+ failure : fail
+ identity : id
+ reflexivity : refl
+ progress : progress `s`
+ failure_catch : try `s`
+ composition : `s` ; `u`
left_biased_choice : choice `s` `t`
- iteration_one_or_more : `repeat` `s`
- iteration_zero_or_more : `any` `s`
+ iteration_one_or_more : repeat `s`
+ iteration_zero_or_more : any `s`
one_subterm : subterm `s`
all_subterms : subterms `s`
- innermost_first : `innermost` `s`
- outermost_first : `outermost` `s`
- bottom_up : `bottomup` `s`
- top_down : `topdown` `s`
+ innermost_first : innermost `s`
+ outermost_first : outermost `s`
+ bottom_up : bottomup `s`
+ top_down : topdown `s`
apply_hint : hints `hintdb`
any_of_the_terms : terms (`c`)+
apply_reduction : eval `redexpr`
@@ -767,7 +767,7 @@ primitive fixpoint operator:
.. productionlist:: rewriting
try `s` : choice `s` `id`
any `s` : fix `u`. try (`s` ; `u`)
- repeat `s` : `s` ; `any` `s`
+ repeat `s` : `s` ; any `s`
bottomup s : fix `bu`. (choice (progress (subterms bu)) s) ; try bu
topdown s : fix `td`. (choice s (progress (subterms td))) ; try td
innermost s : fix `i`. (choice (subterm i) s)
diff --git a/doc/sphinx/addendum/implicit-coercions.rst b/doc/sphinx/addendum/implicit-coercions.rst
index 64e2d7c4ab..e5b41be691 100644
--- a/doc/sphinx/addendum/implicit-coercions.rst
+++ b/doc/sphinx/addendum/implicit-coercions.rst
@@ -41,8 +41,8 @@ Formally, the syntax of a classes is defined as:
.. productionlist::
class: `qualid`
- : | Sortclass
- : | Funclass
+ : Sortclass
+ : Funclass
Coercions
@@ -184,10 +184,10 @@ Figure :ref:`vernacular` as follows:
\comindex{Hypothesis \mbox{\rm (and coercions)}}
.. productionlist::
- assumption : assumption_keyword assums .
- assums : simple_assums
- : | (simple_assums) ... (simple_assums)
- simple_assums : ident ... ident :[>] term
+ assumption : `assumption_keyword` `assums` .
+ assums : `simple_assums`
+ : (`simple_assums`) ... (`simple_assums`)
+ simple_assums : `ident` ... `ident` :[>] `term`
If the extra ``>`` is present before the type of some assumptions, these
assumptions are declared as coercions.
@@ -203,7 +203,7 @@ grammar of inductive types from Figure :ref:`vernacular` as follows:
.. productionlist::
inductive : Inductive `ind_body` with ... with `ind_body`
- : | CoInductive `ind_body` with ... with `ind_body`
+ : CoInductive `ind_body` with ... with `ind_body`
ind_body : `ident` [ `binders` ] : `term` := [[|] `constructor` | ... | `constructor` ]
constructor : `ident` [ `binders` ] [:[>] `term` ]
diff --git a/doc/sphinx/addendum/micromega.rst b/doc/sphinx/addendum/micromega.rst
index fd66de427c..b076aac1ed 100644
--- a/doc/sphinx/addendum/micromega.rst
+++ b/doc/sphinx/addendum/micromega.rst
@@ -38,7 +38,7 @@ The tactics solve propositional formulas parameterized by atomic
arithmetic expressions interpreted over a domain :math:`D \in \{\mathbb{Z},\mathbb{Q},\mathbb{R}\}`.
The syntax of the formulas is the following:
- .. productionlist:: `F`
+ .. productionlist:: F
F : A ∣ P ∣ True ∣ False ∣ F ∧ F ∣ F ∨ F ∣ F ↔ F ∣ F → F ∣ ¬ F
A : p = p ∣ p > p ∣ p < p ∣ p ≥ p ∣ p ≤ p
p : c ∣ x ∣ −p ∣ p − p ∣ p + p ∣ p × p ∣ p ^ n
@@ -145,7 +145,7 @@ weakness, the :tacn:`lia` tactic is using recursively a combination of:
+ linear *positivstellensatz* refutations;
+ cutting plane proofs;
+ case split.
-
+
Cutting plane proofs
~~~~~~~~~~~~~~~~~~~~~~
@@ -250,6 +250,16 @@ obtain :math:`-1`. By Theorem :ref:`Psatz <psatz_thm>`, the goal is valid.
.. [#] Support for :g:`nat` and :g:`N` is obtained by pre-processing the goal with
the ``zify`` tactic.
+.. [#] Support for :g:`Z.div` and :g:`Z.modulo` may be obtained by
+ pre-processing the goal with the ``Z.div_mod_to_equations`` tactic (you may
+ need to manually run ``zify`` first).
+.. [#] Support for :g:`Z.quot` and :g:`Z.rem` may be obtained by pre-processing
+ the goal with the ``Z.quot_rem_to_equations`` tactic (you may need to manually
+ run ``zify`` first).
+.. [#] Note that support for :g:`Z.div`, :g:`Z.modulo`, :g:`Z.quot`, and
+ :g:`Z.rem` may be simultaneously obtained by pre-processing the goal with the
+ ``Z.to_euclidean_division_equations`` tactic (you may need to manually run
+ ``zify`` first).
.. [#] Sources and binaries can be found at https://projects.coin-or.org/Csdp
.. [#] Variants deal with equalities and strict inequalities.
.. [#] In practice, the oracle might fail to produce such a refutation.
diff --git a/doc/sphinx/addendum/parallel-proof-processing.rst b/doc/sphinx/addendum/parallel-proof-processing.rst
index 8b7214e2ab..903ee115c9 100644
--- a/doc/sphinx/addendum/parallel-proof-processing.rst
+++ b/doc/sphinx/addendum/parallel-proof-processing.rst
@@ -52,7 +52,7 @@ in interactive mode.
It is not strictly mandatory in batch mode if it is not the first time
the file is compiled and if the file itself did not change. When the
proof does not begin with Proof using, the system records in an
-auxiliary file, produced along with the `.vo` file, the list of section
+auxiliary file, produced along with the ``.vo`` file, the list of section
variables used.
Automatic suggestion of proof annotations
@@ -154,22 +154,22 @@ to a worker process. The threshold can be configured with
Batch mode
---------------
-When |Coq| is used as a batch compiler by running `coqc` or `coqtop`
--compile, it produces a `.vo` file for each `.v` file. A `.vo` file contains,
-among other things, theorem statements and proofs. Hence to produce a
-.vo |Coq| need to process all the proofs of the `.v` file.
+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|
+need to process all the proofs of the ``.v`` file.
The asynchronous processing of proofs can decouple the generation of a
-compiled file (like the `.vo` one) that can be loaded by ``Require`` from the
+compiled file (like the ``.vo`` one) that can be loaded by ``Require`` from the
generation and checking of the proof objects. The ``-quick`` flag can be
-passed to `coqc` or `coqtop` to produce, quickly, `.vio` files.
-Alternatively, when using a Makefile produced by `coq_makefile`,
+passed to ``coqc`` or ``coqtop`` to produce, quickly, ``.vio`` files.
+Alternatively, when using a Makefile produced by ``coq_makefile``,
the ``quick`` target can be used to compile all files using the ``-quick`` flag.
-A `.vio` file can be loaded using ``Require`` exactly as a `.vo` file but
+A ``.vio`` file can be loaded using ``Require`` exactly as a ``.vo`` file but
proofs will not be available (the Print command produces an error).
Moreover, some universe constraints might be missing, so universes
-inconsistencies might go unnoticed. A `.vio` file does not contain proof
+inconsistencies might go unnoticed. A ``.vio`` file does not contain proof
objects, but proof tasks, i.e. what a worker process can transform
into a proof object.
@@ -177,52 +177,52 @@ Compiling a set of files with the ``-quick`` flag allows one to work,
interactively, on any file without waiting for all the proofs to be
checked.
-When working interactively, one can fully check all the `.v` files by
-running `coqc` as usual.
+When working interactively, one can fully check all the ``.v`` files by
+running ``coqc`` as usual.
-Alternatively one can turn each `.vio` into the corresponding `.vo`. All
+Alternatively one can turn each ``.vio`` into the corresponding ``.vo``. All
.vio files can be processed in parallel, hence this alternative might
be faster. The command ``coqtop -schedule-vio2vo 2 a b c`` can be used to
-obtain a good scheduling for two workers to produce `a.vo`, `b.vo`, and
-`c.vo`. When using a Makefile produced by `coq_makefile`, the ``vio2vo`` target
-can be used for that purpose. Variable `J` should be set to the number
+obtain a good scheduling for two workers to produce ``a.vo``, ``b.vo``, and
+``c.vo``. When using a Makefile produced by ``coq_makefile``, the ``vio2vo`` target
+can be used for that purpose. Variable ``J`` should be set to the number
of workers, e.g. ``make vio2vo J=2``. The only caveat is that, while the
-.vo files obtained from `.vio` files are complete (they contain all proof
+.vo files obtained from ``.vio`` files are complete (they contain all proof
terms and universe constraints), the satisfiability of all universe
constraints has not been checked globally (they are checked to be
consistent for every single proof). Constraints will be checked when
-these `.vo` files are (recursively) loaded with ``Require``.
+these ``.vo`` files are (recursively) loaded with ``Require``.
There is an extra, possibly even faster, alternative: just check the
-proof tasks stored in `.vio` files without producing the `.vo` files. This
+proof tasks stored in ``.vio`` files without producing the ``.vo`` files. This
is possibly faster because all the proof tasks are independent, hence
one can further partition the job to be done between workers. The
``coqtop -schedule-vio-checking 6 a b c`` command can be used to obtain a
-good scheduling for 6 workers to check all the proof tasks of `a.vio`,
-`b.vio`, and `c.vio`. Auxiliary files are used to predict how long a proof
+good scheduling for 6 workers to check all the proof tasks of ``a.vio``,
+``b.vio``, and ``c.vio``. Auxiliary files are used to predict how long a proof
task will take, assuming it will take the same amount of time it took
last time. When using a Makefile produced by coq_makefile, the
-``checkproofs`` target can be used to check all `.vio` files. Variable `J`
+``checkproofs`` target can be used to check all ``.vio`` files. Variable ``J``
should be set to the number of workers, e.g. ``make checkproofs J=6``. As
-when converting `.vio` files to `.vo` files, universe constraints are not
+when converting ``.vio`` files to ``.vo`` files, universe constraints are not
checked to be globally consistent. Hence this compilation mode is only
useful for quick regression testing and on developments not making
-heavy use of the `Type` hierarchy.
+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
-start many additional worker processes. The `coqworkmgr` utility lets
+start many additional worker processes. The ``coqworkmgr`` utility lets
one limit the number of workers, globally.
The utility accepts the ``-j`` argument to specify the maximum number of
-workers (defaults to 2). `coqworkmgr` automatically starts in the
+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
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/ring.rst b/doc/sphinx/addendum/ring.rst
index 99d689132d..8204d93fa7 100644
--- a/doc/sphinx/addendum/ring.rst
+++ b/doc/sphinx/addendum/ring.rst
@@ -308,13 +308,13 @@ The syntax for adding a new ring is
.. productionlist:: coq
ring_mod : abstract | decidable `term` | morphism `term`
- : | setoid `term` `term`
- : | constants [`ltac`]
- : | preprocess [`ltac`]
- : | postprocess [`ltac`]
- : | power_tac `term` [`ltac`]
- : | sign `term`
- : | div `term`
+ : setoid `term` `term`
+ : constants [`ltac`]
+ : preprocess [`ltac`]
+ : postprocess [`ltac`]
+ : power_tac `term` [`ltac`]
+ : sign `term`
+ : div `term`
abstract
declares the ring as abstract. This is the default.
diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst
index 693ee28a47..67683902cd 100644
--- a/doc/sphinx/language/cic.rst
+++ b/doc/sphinx/language/cic.rst
@@ -84,7 +84,7 @@ implemented using *algebraic
universes*. An algebraic universe :math:`u` is either a variable (a qualified
identifier with a number) or a successor of an algebraic universe (an
expression :math:`u+1`), or an upper bound of algebraic universes (an
-expression :math:`\max(u 1 ,...,u n )`), or the base universe (the expression
+expression :math:`\max(u_1 ,...,u_n )`), or the base universe (the expression
:math:`0`) which corresponds, in the arity of template polymorphic inductive
types (see Section
:ref:`well-formed-inductive-definitions`),
@@ -117,24 +117,24 @@ 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.
- If :math:`x` occurs in :math:`U`, :math:`∀ x:T,U` reads as
+ :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
+ As :math:`U` depends on :math:`x`, one says that :math:`∀ x:T,~U` is
a *dependent product*. If :math:`x` does not occur in :math:`U` then
- :math:`∀ x:T,U` reads as
+ :math:`∀ x:T,~U` reads as
“if :math:`T` then :math:`U`”. A *non dependent product* can be
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`
+ :math:`λ x:T .~u` (:g:`fun x:T => u`
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
+ λ-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
syntax). The term :math:`(t~u)` reads as “t applied to u”.
-#. if :g:`x` is a variable, and :math:`t`, :math:`T` and :math:`u` are
- terms then :g:`let x:=t:T in u` is
+#. if :math:`x` is a variable, and :math:`t`, :math:`T` and :math:`u` are
+ terms then :math:`\letin{x}{t:T}{u}` is
a term which denotes the term :math:`u` where the variable :math:`x` is locally bound
to :math:`t` of type :math:`T`. This stands for the common “let-in” construction of
functional programs such as ML or Scheme.
@@ -145,7 +145,7 @@ the following rules.
**Free variables.**
The notion of free variables is defined as usual. In the expressions
-:g:`λx:T. U` and :g:`∀ x:T, U` the occurrences of :math:`x` in :math:`U` are bound.
+:math:`λx:T.~U` and :math:`∀ x:T,~U` the occurrences of :math:`x` in :math:`U` are bound.
.. _Substitution:
@@ -172,11 +172,11 @@ implicative proposition, to denote :math:`\nat →\Prop` which is the type of
unary predicates over the natural numbers, etc.
Let us assume that ``mult`` is a function of type :math:`\nat→\nat→\nat` and ``eqnat`` a
-predicate of type \nat→\nat→ \Prop. The λ-abstraction can serve to build
-“ordinary” functions as in :math:`λ x:\nat.(\kw{mult}~x~x)` (i.e.
+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
-numbers. For instance :math:`λ x:\nat.(\kw{eqnat}~x~0)`
+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
asserts the equality of :math:`x` with :math:`0`. This predicate has type
@@ -186,7 +186,7 @@ object :math:`P~t` of type :math:`\Prop`, namely a proposition.
Furthermore :g:`forall x:nat, P x` will represent the type of functions
which associate to each natural number :math:`n` an object of type :math:`(P~n)` and
-consequently represent the type of proofs of the formula “:math:`∀ x. P(x`)”.
+consequently represent the type of proofs of the formula “:math:`∀ x.~P(x)`”.
.. _Typing-rules:
@@ -206,7 +206,7 @@ A *local context* is an ordered list of *local declarations* of names
which we call *variables*. The declaration of some variable :math:`x` is
either a *local assumption*, written :math:`x:T` (:math:`T` is a type) or a *local
definition*, written :math:`x:=t:T`. We use brackets to write local contexts.
-A typical example is :math:`[x:T;y:=u:U;z:V]`. Notice that the variables
+A typical example is :math:`[x:T;~y:=u:U;~z:V]`. Notice that the variables
declared in a local context must be distinct. If :math:`Γ` is a local context
that declares some :math:`x`, we
write :math:`x ∈ Γ`. By writing :math:`(x:T) ∈ Γ` we mean that either :math:`x:T` is an
@@ -232,9 +232,9 @@ A *global assumption* will be represented in the global environment as
:math:`(c:T)` which assumes the name :math:`c` to be of some type :math:`T`. A *global
definition* will be represented in the global environment as :math:`c:=t:T`
which defines the name :math:`c` to have value :math:`t` and type :math:`T`. We shall call
-such names *constants*. For the rest of the chapter, the :math:`E;c:T` denotes
+such names *constants*. For the rest of the chapter, the :math:`E;~c:T` denotes
the global environment :math:`E` enriched with the global assumption :math:`c:T`.
-Similarly, :math:`E;c:=t:T` denotes the global environment :math:`E` enriched with the
+Similarly, :math:`E;~c:=t:T` denotes the global environment :math:`E` enriched with the
global definition :math:`(c:=t:T)`.
The rules for inductive definitions (see Section
@@ -284,14 +284,14 @@ following rules.
s \in \Sort
c \notin E
------------
- \WF{E;c:T}{}
+ \WF{E;~c:T}{}
.. inference:: W-Global-Def
\WTE{}{t}{T}
c \notin E
---------------
- \WF{E;c:=t:T}{}
+ \WF{E;~c:=t:T}{}
.. inference:: Ax-Prop
@@ -328,10 +328,10 @@ following rules.
.. inference:: Prod-Prop
\WTEG{T}{s}
- s \in {\Sort}
+ s \in \Sort
\WTE{\Gamma::(x:T)}{U}{\Prop}
-----------------------------
- \WTEG{\forall~x:T,U}{\Prop}
+ \WTEG{∀ x:T,~U}{\Prop}
.. inference:: Prod-Set
@@ -339,25 +339,25 @@ following rules.
s \in \{\Prop, \Set\}
\WTE{\Gamma::(x:T)}{U}{\Set}
----------------------------
- \WTEG{\forall~x:T,U}{\Set}
+ \WTEG{∀ x:T,~U}{\Set}
.. inference:: Prod-Type
\WTEG{T}{\Type(i)}
\WTE{\Gamma::(x:T)}{U}{\Type(i)}
--------------------------------
- \WTEG{\forall~x:T,U}{\Type(i)}
+ \WTEG{∀ x:T,~U}{\Type(i)}
.. inference:: Lam
- \WTEG{\forall~x:T,U}{s}
+ \WTEG{∀ x:T,~U}{s}
\WTE{\Gamma::(x:T)}{t}{U}
------------------------------------
- \WTEG{\lb x:T\mto t}{\forall x:T, U}
+ \WTEG{λ x:T\mto t}{∀ x:T,~U}
.. inference:: App
- \WTEG{t}{\forall~x:U,T}
+ \WTEG{t}{∀ x:U,~T}
\WTEG{u}{U}
------------------------------
\WTEG{(t\ u)}{\subst{T}{x}{u}}
@@ -383,7 +383,7 @@ following rules.
.. note::
We may have :math:`\letin{x}{t:T}{u}` well-typed without having
- :math:`((λ x:T.u) t)` well-typed (where :math:`T` is a type of
+ :math:`((λ x:T.~u)~t)` well-typed (where :math:`T` is a type of
:math:`t`). This is because the value :math:`t` associated to
:math:`x` may be used in a conversion rule
(see Section :ref:`Conversion-rules`).
@@ -406,18 +406,18 @@ can decide if two programs are *intentionally* equal (one says
We want to be able to identify some terms as we can identify the
application of a function to a given argument with its result. For
-instance the identity function over a given type T can be written
-:math:`λx:T. x`. In any global environment :math:`E` and local context
+instance the identity function over a given type :math:`T` can be written
+:math:`λx:T.~x`. In any global environment :math:`E` and local context
:math:`Γ`, we want to identify any object :math:`a` (of type
-:math:`T`) with the application :math:`((λ x:T. x) a)`. We define for
+:math:`T`) with the application :math:`((λ x:T.~x)~a)`. We define for
this a *reduction* (or a *conversion*) rule we call :math:`β`:
.. math::
- E[Γ] ⊢ ((λx:T. t) u)~\triangleright_β~\subst{t}{x}{u}
+ E[Γ] ⊢ ((λx:T.~t)~u)~\triangleright_β~\subst{t}{x}{u}
We say that :math:`\subst{t}{x}{u}` is the *β-contraction* of
-:math:`((λx:T. t) u)` and, conversely, that :math:`((λ x:T. t) u)` is the
+:math:`((λx:T.~t)~u)` and, conversely, that :math:`((λ x:T.~t)~u)` is the
*β-expansion* of :math:`\subst{t}{x}{u}`.
According to β-reduction, terms of the *Calculus of Inductive
@@ -481,7 +481,7 @@ destroyed, this reduction differs from δ-reduction. It is called
\WTEG{u}{U}
\WTE{\Gamma::(x:=u:U)}{t}{T}
--------------
- E[Γ] ⊢ \letin{x}{u}{t}~\triangleright_ζ~\subst{t}{x}{u}
+ E[Γ] ⊢ \letin{x}{u:U}{t}~\triangleright_ζ~\subst{t}{x}{u}
.. _eta-expansion:
@@ -490,10 +490,10 @@ destroyed, this reduction differs from δ-reduction. It is called
~~~~~~~~~~~
Another important concept is η-expansion. It is legal to identify any
-term :math:`t` of functional type :math:`∀ x:T, U` with its so-called η-expansion
+term :math:`t` of functional type :math:`∀ x:T,~U` with its so-called η-expansion
.. math::
- λx:T. (t~x)
+ λx:T.~(t~x)
for :math:`x` an arbitrary variable name fresh in :math:`t`.
@@ -503,26 +503,26 @@ for :math:`x` an arbitrary variable name fresh in :math:`t`.
We deliberately do not define η-reduction:
.. math::
- λ x:T. (t~x) \not\triangleright_η t
+ λ x:T.~(t~x)~\not\triangleright_η~t
This is because, in general, the type of :math:`t` need not to be convertible
- to the type of :math:`λ x:T. (t~x)`. E.g., if we take :math:`f` such that:
+ to the type of :math:`λ x:T.~(t~x)`. E.g., if we take :math:`f` such that:
.. math::
- f : ∀ x:\Type(2),\Type(1)
+ f ~:~ ∀ x:\Type(2),~\Type(1)
then
.. math::
- λ x:\Type(1),(f~x) : ∀ x:\Type(1),\Type(1)
+ λ x:\Type(1).~(f~x) ~:~ ∀ x:\Type(1),~\Type(1)
We could not allow
.. math::
- λ x:Type(1),(f x) \triangleright_η f
+ λ x:\Type(1).~(f~x) ~\triangleright_η~ f
- because the type of the reduced term :math:`∀ x:\Type(2),\Type(1)` would not be
- convertible to the type of the original term :math:`∀ x:\Type(1),\Type(1).`
+ because the type of the reduced term :math:`∀ x:\Type(2),~\Type(1)` would not be
+ convertible to the type of the original term :math:`∀ x:\Type(1),~\Type(1)`.
.. _convertibility:
@@ -541,10 +541,10 @@ global environment :math:`E` and local context :math:`Γ` iff there
exist terms :math:`u_1` and :math:`u_2` such that :math:`E[Γ] ⊢ t_1 \triangleright
… \triangleright u_1` and :math:`E[Γ] ⊢ t_2 \triangleright … \triangleright u_2` and either :math:`u_1` and
:math:`u_2` are identical, or they are convertible up to η-expansion,
-i.e. :math:`u_1` is :math:`λ x:T. u_1'` and :math:`u_2 x` is
+i.e. :math:`u_1` is :math:`λ x:T.~u_1'` and :math:`u_2 x` is
recursively convertible to :math:`u_1'` , or, symmetrically,
-:math:`u_2` is :math:`λx:T. u_2'`
-and :math:`u_1 x` is recursively convertible to u_2′ . We then write
+:math:`u_2` is :math:`λx:T.~u_2'`
+and :math:`u_1 x` is recursively convertible to :math:`u_2'`. We then write
:math:`E[Γ] ⊢ t_1 =_{βδιζη} t_2` .
Apart from this we consider two instances of polymorphic and
@@ -601,8 +601,8 @@ Subtyping rules
-------------------
At the moment, we did not take into account one rule between universes
-which says that any term in a universe of index i is also a term in
-the universe of index i+1 (this is the *cumulativity* rule of |Cic|).
+which says that any term in a universe of index :math:`i` is also a term in
+the universe of index :math:`i+1` (this is the *cumulativity* rule of |Cic|).
This property extends the equivalence relation of convertibility into
a *subtyping* relation inductively defined by:
@@ -614,25 +614,25 @@ a *subtyping* relation inductively defined by:
:math:`E[Γ] ⊢ \Prop ≤_{βδιζη} \Type(i)`, for any :math:`i`
#. if :math:`E[Γ] ⊢ T =_{βδιζη} U` and
:math:`E[Γ::(x:T)] ⊢ T' ≤_{βδιζη} U'` then
- :math:`E[Γ] ⊢ ∀x:T, T′ ≤_{βδιζη} ∀ x:U, U′`.
+ :math:`E[Γ] ⊢ ∀x:T,~T′ ≤_{βδιζη} ∀ x:U,~U′`.
#. if :math:`\ind{p}{Γ_I}{Γ_C}` is a universe polymorphic and cumulative
(see Chapter :ref:`polymorphicuniverses`) inductive type (see below)
and
- :math:`(t : ∀Γ_P ,∀Γ_{\mathit{Arr}(t)}, \Sort)∈Γ_I`
+ :math:`(t : ∀Γ_P ,∀Γ_{\mathit{Arr}(t)}, S)∈Γ_I`
and
- :math:`(t' : ∀Γ_P' ,∀Γ_{\mathit{Arr}(t)}', \Sort')∈Γ_I`
+ :math:`(t' : ∀Γ_P' ,∀Γ_{\mathit{Arr}(t)}', S')∈Γ_I`
are two different instances of *the same* inductive type (differing only in
universe levels) with constructors
.. math::
- [c_1 : ∀Γ_P ,∀ T_{1,1} … T_{1,n_1} , t~v_{1,1} … v_{1,m} ;…;
- c_k : ∀Γ_P ,∀ T_{k,1} … T_{k,n_k} ,t~v_{n,1} … v_{n,m} ]
+ [c_1 : ∀Γ_P ,∀ T_{1,1} … T_{1,n_1} ,~t~v_{1,1} … v_{1,m} ;~…;~
+ c_k : ∀Γ_P ,∀ T_{k,1} … T_{k,n_k} ,~t~v_{k,1} … v_{k,m} ]
and
.. math::
- [c_1 : ∀Γ_P' ,∀ T_{1,1}' … T_{1,n_1}' , t'~v_{1,1}' … v_{1,m}' ;…;
- c_k : ∀Γ_P' ,∀ T_{k,1}' … T_{k,n_k}' ,t'~v_{n,1}' … v_{n,m}' ]
+ [c_1 : ∀Γ_P' ,∀ T_{1,1}' … T_{1,n_1}' ,~t'~v_{1,1}' … v_{1,m}' ;~…;~
+ c_k : ∀Γ_P' ,∀ T_{k,1}' … T_{k,n_k}' ,~t'~v_{k,1}' … v_{k,m}' ]
respectively then
@@ -656,8 +656,8 @@ a *subtyping* relation inductively defined by:
.. math::
E[Γ] ⊢ A_i ≤_{βδιζη} A_i'
- where :math:`Γ_{\mathit{Arr}(t)} = [a_1 : A_1 ; … ; a_l : A_l ]` and
- :math:`Γ_{\mathit{Arr}(t)}' = [a_1 : A_1'; … ; a_l : A_l']`.
+ where :math:`Γ_{\mathit{Arr}(t)} = [a_1 : A_1 ;~ … ;~a_l : A_l ]` and
+ :math:`Γ_{\mathit{Arr}(t)}' = [a_1 : A_1';~ … ;~a_l : A_l']`.
The conversion rule up to subtyping is now exactly:
@@ -677,19 +677,19 @@ The conversion rule up to subtyping is now exactly:
form*. There are several ways (or strategies) to apply the reduction
rules. Among them, we have to mention the *head reduction* which will
play an important role (see Chapter :ref:`tactics`). Any term :math:`t` can be written as
-:math:`λ x_1 :T_1 . … λ x_k :T_k . (t_0~t_1 … t_n )` where :math:`t_0` is not an
+:math:`λ x_1 :T_1 .~… λ x_k :T_k .~(t_0~t_1 … t_n )` where :math:`t_0` is not an
application. We say then that :math:`t_0` is the *head of* :math:`t`. If we assume
-that :math:`t_0` is :math:`λ x:T. u_0` then one step of β-head reduction of :math:`t` is:
+that :math:`t_0` is :math:`λ x:T.~u_0` then one step of β-head reduction of :math:`t` is:
.. math::
- λ x_1 :T_1 . … λ x_k :T_k . (λ x:T. u_0~t_1 … t_n ) \triangleright
- λ (x_1 :T_1 )…(x_k :T_k ). (\subst{u_0}{x}{t_1}~t_2 … t_n )
+ λ x_1 :T_1 .~… λ x_k :T_k .~(λ x:T.~u_0~t_1 … t_n ) ~\triangleright~
+ λ (x_1 :T_1 )…(x_k :T_k ).~(\subst{u_0}{x}{t_1}~t_2 … t_n )
Iterating the process of head reduction until the head of the reduced
term is no more an abstraction leads to the *β-head normal form* of :math:`t`:
.. math::
- t \triangleright … \triangleright λ x_1 :T_1 . …λ x_k :T_k . (v~u_1 … u_m )
+ t \triangleright … \triangleright λ x_1 :T_1 .~…λ x_k :T_k .~(v~u_1 … u_m )
where :math:`v` is not an abstraction (nor an application). Note that the head
normal form must not be confused with the normal form since some :math:`u_i`
@@ -713,12 +713,12 @@ Formally, we can represent any *inductive definition* as
These inductive definitions, together with global assumptions and
global definitions, then form the global environment. Additionally,
-for any :math:`p` there always exists :math:`Γ_P =[a_1 :A_1 ;…;a_p :A_p ]` such that
+for any :math:`p` there always exists :math:`Γ_P =[a_1 :A_1 ;~…;~a_p :A_p ]` such that
each :math:`T` in :math:`(t:T)∈Γ_I \cup Γ_C` can be written as: :math:`∀Γ_P , T'` where :math:`Γ_P` is
called the *context of parameters*. Furthermore, we must have that
each :math:`T` in :math:`(t:T)∈Γ_I` can be written as: :math:`∀Γ_P,∀Γ_{\mathit{Arr}(t)}, S` where
-:math:`Γ_{\mathit{Arr}(t)}` is called the *Arity* of the inductive type t and :math:`S` is called
-the sort of the inductive type t (not to be confused with :math:`\Sort` which is the set of sorts).
+:math:`Γ_{\mathit{Arr}(t)}` is called the *Arity* of the inductive type :math:`t` and :math:`S` is called
+the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort` which is the set of sorts).
.. example::
@@ -726,8 +726,8 @@ the sort of the inductive type t (not to be confused with :math:`\Sort` which is
.. math::
\ind{1}{[\List:\Set→\Set]}{\left[\begin{array}{rcl}
- \Nil & : & \forall A:\Set,\List~A \\
- \cons & : & \forall A:\Set, A→ \List~A→ \List~A
+ \Nil & : & ∀ A:\Set,~\List~A \\
+ \cons & : & ∀ A:\Set,~A→ \List~A→ \List~A
\end{array}
\right]}
@@ -771,8 +771,8 @@ the sort of the inductive type t (not to be confused with :math:`\Sort` which is
\odd&:&\nat → \Prop \end{array}\right]}
{\left[\begin{array}{rcl}
\evenO &:& \even~0\\
- \evenS &:& \forall n, \odd~n → \even~(\kw{S}~n)\\
- \oddS &:& \forall n, \even~n → \odd~(\kw{S}~n)
+ \evenS &:& ∀ n,~\odd~n → \even~(\nS~n)\\
+ \oddS &:& ∀ n,~\even~n → \odd~(\nS~n)
\end{array}\right]}
which corresponds to the result of the |Coq| declaration:
@@ -792,7 +792,7 @@ the sort of the inductive type t (not to be confused with :math:`\Sort` which is
Types of inductive objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We have to give the type of constants in a global environment E which
+We have to give the type of constants in a global environment :math:`E` which
contains an inductive declaration.
.. inference:: Ind
@@ -820,9 +820,9 @@ contains an inductive declaration.
\begin{array}{l}
E[Γ] ⊢ \even : \nat→\Prop\\
E[Γ] ⊢ \odd : \nat→\Prop\\
- E[Γ] ⊢ \even\_O : \even~O\\
- E[Γ] ⊢ \even\_S : \forall~n:\nat, \odd~n → \even~(S~n)\\
- E[Γ] ⊢ \odd\_S : \forall~n:\nat, \even~n → \odd~(S~n)
+ E[Γ] ⊢ \evenO : \even~\nO\\
+ E[Γ] ⊢ \evenS : ∀ n:\nat,~\odd~n → \even~(\nS~n)\\
+ E[Γ] ⊢ \oddS : ∀ n:\nat,~\even~n → \odd~(\nS~n)
\end{array}
@@ -842,11 +842,11 @@ Arity of a given sort
+++++++++++++++++++++
A type :math:`T` is an *arity of sort* :math:`s` if it converts to the sort :math:`s` or to a
-product :math:`∀ x:T,U` with :math:`U` an arity of sort :math:`s`.
+product :math:`∀ x:T,~U` with :math:`U` an arity of sort :math:`s`.
.. example::
- :math:`A→\Set` is an arity of sort :math:`\Set`. :math:`∀ A:\Prop,A→ \Prop` is an arity of sort
+ :math:`A→\Set` is an arity of sort :math:`\Set`. :math:`∀ A:\Prop,~A→ \Prop` is an arity of sort
:math:`\Prop`.
@@ -858,21 +858,21 @@ sort :math:`s`.
.. example::
- :math:`A→ Set` and :math:`∀ A:\Prop,A→ \Prop` are arities.
+ :math:`A→ \Set` and :math:`∀ A:\Prop,~A→ \Prop` are arities.
-Type constructor
-++++++++++++++++
-We say that T is a *type of constructor of I* in one of the following
+Type of constructor
++++++++++++++++++++
+We say that :math:`T` is a *type of constructor of* :math:`I` in one of the following
two cases:
+ :math:`T` is :math:`(I~t_1 … t_n )`
-+ :math:`T` is :math:`∀ x:U,T'` where :math:`T'` is also a type of constructor of :math:`I`
++ :math:`T` is :math:`∀ x:U,~T'` where :math:`T'` is also a type of constructor of :math:`I`
.. example::
:math:`\nat` and :math:`\nat→\nat` are types of constructor of :math:`\nat`.
- :math:`∀ A:Type,\List~A` and :math:`∀ A:Type,A→\List~A→\List~A` are types of constructor of :math:`\List`.
+ :math:`∀ A:\Type,~\List~A` and :math:`∀ A:\Type,~A→\List~A→\List~A` are types of constructor of :math:`\List`.
.. _positivity:
@@ -883,7 +883,7 @@ The type of constructor :math:`T` will be said to *satisfy the positivity
condition* for a constant :math:`X` in the following cases:
+ :math:`T=(X~t_1 … t_n )` and :math:`X` does not occur free in any :math:`t_i`
-+ :math:`T=∀ x:U,V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V`
++ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V`
satisfies the positivity condition for :math:`X`.
Strict positivity
@@ -895,13 +895,13 @@ cases:
+ :math:`X` does not occur in :math:`T`
+ :math:`T` converts to :math:`(X~t_1 … t_n )` and :math:`X` does not occur in any of :math:`t_i`
-+ :math:`T` converts to :math:`∀ x:U,V` and :math:`X` does not occur in type :math:`U` but occurs
++ :math:`T` converts to :math:`∀ x:U,~V` and :math:`X` does not occur in type :math:`U` but occurs
strictly positively in type :math:`V`
+ :math:`T` converts to :math:`(I~a_1 … a_m~t_1 … t_p )` where :math:`I` is the name of an
inductive declaration of the form
.. math::
- \ind{m}{I:A}{c_1 :∀ p_1 :P_1 ,… ∀p_m :P_m ,C_1 ;…;c_n :∀ p_1 :P_1 ,… ∀p_m :P_m ,C_n}
+ \ind{m}{I:A}{c_1 :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_1 ;~…;~c_n :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_n}
(in particular, it is
not mutually defined and it has :math:`m` parameters) and :math:`X` does not occur in
@@ -916,7 +916,7 @@ condition* for a constant :math:`X` in the following cases:
+ :math:`T=(I~b_1 … b_m~u_1 … u_p)`, :math:`I` is an inductive definition with :math:`m`
parameters and :math:`X` does not occur in any :math:`u_i`
-+ :math:`T=∀ x:U,V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V`
++ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V`
satisfies the nested positivity condition for :math:`X`
@@ -930,7 +930,6 @@ condition* for a constant :math:`X` in the following cases:
Inductive nattree (A:Type) : Type :=
| leaf : nattree A
| node : A -> (nat -> nattree A) -> nattree A.
- End TreeExample.
Then every instantiated constructor of ``nattree A`` satisfies the nested positivity
condition for ``nattree``:
@@ -943,7 +942,7 @@ condition* for a constant :math:`X` in the following cases:
+ Type ``A → (nat → nattree A) → nattree A`` of constructor ``node`` satisfies the
positivity condition for ``nattree`` because:
- - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 3)
+ - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 1)
- ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2)
@@ -958,8 +957,8 @@ We shall now describe the rules allowing the introduction of a new
inductive definition.
Let :math:`E` be a global environment and :math:`Γ_P`, :math:`Γ_I`, :math:`Γ_C` be contexts
-such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;…;I_k :∀ Γ_P ,A_k]`, and
-:math:`Γ_C` is :math:`[c_1:∀ Γ_P ,C_1 ;…;c_n :∀ Γ_P ,C_n ]`. Then
+such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k]`, and
+:math:`Γ_C` is :math:`[c_1:∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n ]`. Then
.. inference:: W-Ind
@@ -967,7 +966,7 @@ such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;…;I_k :∀ Γ_P ,A_k]`,
(E[Γ_P ] ⊢ A_j : s_j )_{j=1… k}
(E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n}
------------------------------------------
- \WF{E;\ind{p}{Γ_I}{Γ_C}}{Γ}
+ \WF{E;~\ind{p}{Γ_I}{Γ_C}}{Γ}
provided that the following side conditions hold:
@@ -990,8 +989,8 @@ the Type hierarchy.
.. example::
It is well known that the existential quantifier can be encoded as an
- inductive definition. The following declaration introduces the second-
- order existential quantifier :math:`∃ X.P(X)`.
+ inductive definition. The following declaration introduces the
+ second-order existential quantifier :math:`∃ X.P(X)`.
.. coqtop:: in
@@ -1028,7 +1027,7 @@ in :math:`\Type`.
.. flag:: Auto Template Polymorphism
This option, enabled by default, makes every inductive type declared
- at level :math:`Type` (without annotations or hiding it behind a
+ at level :math:`\Type` (without annotations or hiding it behind a
definition) template polymorphic.
This can be prevented using the ``notemplate`` attribute.
@@ -1055,9 +1054,9 @@ Calculus of Inductive Constructions. The following typing rule is
added to the theory.
Let :math:`\ind{p}{Γ_I}{Γ_C}` be an inductive definition. Let
-:math:`Γ_P = [p_1 :P_1 ;…;p_p :P_p ]` be its context of parameters,
-:math:`Γ_I = [I_1:∀ Γ_P ,A_1 ;…;I_k :∀ Γ_P ,A_k ]` its context of definitions and
-:math:`Γ_C = [c_1 :∀ Γ_P ,C_1 ;…;c_n :∀ Γ_P ,C_n]` its context of constructors,
+:math:`Γ_P = [p_1 :P_1 ;~…;~p_p :P_p ]` be its context of parameters,
+:math:`Γ_I = [I_1:∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k ]` its context of definitions and
+:math:`Γ_C = [c_1 :∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n]` its context of constructors,
with :math:`c_i` a constructor of :math:`I_{q_i}`. Let :math:`m ≤ p` be the length of the
longest prefix of parameters such that the :math:`m` first arguments of all
occurrences of all :math:`I_j` in all :math:`C_k` (even the occurrences in the
@@ -1077,15 +1076,15 @@ uniform parameters of :math:`Γ_P` . We have:
\end{array}
\right.
-----------------------------
- E[] ⊢ I_j~q_1 … q_r :∀ [p_{r+1} :P_{r+1} ;…;p_p :P_p], (A_j)_{/s_j}
+ E[] ⊢ I_j~q_1 … q_r :∀ [p_{r+1} :P_{r+1} ;~…;~p_p :P_p], (A_j)_{/s_j}
provided that the following side conditions hold:
+ :math:`Γ_{P′}` is the context obtained from :math:`Γ_P` by replacing each :math:`P_l` that is
an arity with :math:`P_l'` for :math:`1≤ l ≤ r` (notice that :math:`P_l` arity implies :math:`P_l'`
- arity since :math:`(E[] ⊢ P_l' ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1} )`;
+ arity since :math:`E[] ⊢ P_l' ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1}`);
+ there are sorts :math:`s_i` , for :math:`1 ≤ i ≤ k` such that, for
- :math:`Γ_{I'} = [I_1 :∀ Γ_{P'} ,(A_1)_{/s_1} ;…;I_k :∀ Γ_{P'} ,(A_k)_{/s_k}]`
+ :math:`Γ_{I'} = [I_1 :∀ Γ_{P'} ,(A_1)_{/s_1} ;~…;~I_k :∀ Γ_{P'} ,(A_k)_{/s_k}]`
we have :math:`(E[Γ_{I′} ;Γ_{P′}] ⊢ C_i : s_{q_i})_{i=1… n}` ;
+ the sorts :math:`s_i` are such that all eliminations, to
:math:`\Prop`, :math:`\Set` and :math:`\Type(j)`, are allowed
@@ -1103,7 +1102,7 @@ replacements of sorts, needed for this derivation, in the parameters
that are arities (this is possible because :math:`\ind{p}{Γ_I}{Γ_C}` well-formed
implies that :math:`\ind{p}{Γ_{I'}}{Γ_{C'}}` is well-formed and has the
same allowed eliminations, where :math:`Γ_{I′}` is defined as above and
-:math:`Γ_{C′} = [c_1 :∀ Γ_{P′} ,C_1 ;…;c_n :∀ Γ_{P′} ,C_n ]`). That is, the changes in the
+:math:`Γ_{C′} = [c_1 :∀ Γ_{P′} ,C_1 ;~…;~c_n :∀ Γ_{P′} ,C_n ]`). That is, the changes in the
types of each partial instance :math:`q_1 … q_r` can be characterized by the
ordered sets of arity sorts among the types of parameters, and to each
signature is associated a new inductive definition with fresh names.
@@ -1205,10 +1204,11 @@ a strongly normalizing reduction, we cannot accept any sort of
recursion (even terminating). So the basic idea is to restrict
ourselves to primitive recursive functions and functionals.
-For instance, assuming a parameter :g:`A:Set` exists in the local context,
-we want to build a function length of type :g:`list A -> nat` which computes
-the length of the list, such that :g:`(length (nil A)) = O` and :g:`(length
-(cons A a l)) = (S (length l))`. We want these equalities to be
+For instance, assuming a parameter :math:`A:\Set` exists in the local context,
+we want to build a function :math:`\length` of type :math:`\List~A → \nat` which computes
+the length of the list, such that :math:`(\length~(\Nil~A)) = \nO` and
+:math:`(\length~(\cons~A~a~l)) = (\nS~(\length~l))`.
+We want these equalities to be
recognized implicitly and taken into account in the conversion rule.
From the logical point of view, we have built a type family by giving
@@ -1222,22 +1222,22 @@ In case the inductive definition is effectively a recursive one, we
want to capture the extra property that we have built the smallest
fixed point of this recursive equation. This says that we are only
manipulating finite objects. This analysis provides induction
-principles. For instance, in order to prove :g:`∀ l:list A,(has_length A l
-(length l))` it is enough to prove:
+principles. For instance, in order to prove
+:math:`∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l))` it is enough to prove:
-+ :g:`(has_length A (nil A) (length (nil A)))`
-+ :g:`∀ a:A, ∀ l:list A, (has_length A l (length l)) →`
- :g:`(has_length A (cons A a l) (length (cons A a l)))`
++ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~(\length~(\Nil~A)))`
++ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →`
+ :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\length~(\cons~A~a~l)))`
-which given the conversion equalities satisfied by length is the same
+which given the conversion equalities satisfied by :math:`\length` is the same
as proving:
-+ :g:`(has_length A (nil A) O)`
-+ :g:`∀ a:A, ∀ l:list A, (has_length A l (length l)) →`
- :g:`(has_length A (cons A a l) (S (length l)))`
++ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~\nO)`
++ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →`
+ :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\nS~(\length~l)))`
One conceptually simple way to do that, following the basic scheme
@@ -1267,7 +1267,7 @@ The |Coq| term for this proof
will be written:
.. math::
- \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n \kwend
+ \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend
In this expression, if :math:`m` eventually happens to evaluate to
:math:`(c_i~u_1 … u_{p_i})` then the expression will behave as specified in its :math:`i`-th branch
@@ -1275,7 +1275,7 @@ and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are repla
:math:`u_1 … u_{p_i}` according to the ι-reduction.
Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need
-to know the predicate P to be proved by case analysis. In the general
+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|
@@ -1309,7 +1309,7 @@ inference rules, we use a more compact notation:
.. _Allowed-elimination-sorts:
-**Allowed elimination sorts.** An important question for building the typing rule for match is what
+**Allowed elimination sorts.** An important question for building the typing rule for :math:`\Match` is what
can be the type of :math:`λ a x . P` with respect to the type of :math:`m`. If :math:`m:I`
and :math:`I:A` and :math:`λ a x . P : B` then by :math:`[I:A|B]` we mean that one can use
:math:`λ a x . P` with :math:`m` in the above match-construct.
@@ -1327,7 +1327,7 @@ There is no restriction on the sort of the predicate to be eliminated.
[(I~x):A′|B′]
-----------------------
- [I:∀ x:A, A′|∀ x:A, B′]
+ [I:∀ x:A,~A′|∀ x:A,~B′]
.. inference:: Set & Type
@@ -1347,7 +1347,7 @@ sort :math:`\Prop`.
~
---------------
- [I:Prop|I→Prop]
+ [I:\Prop|I→\Prop]
:math:`\Prop` is the type of logical propositions, the proofs of properties :math:`P` in
@@ -1376,7 +1376,7 @@ the proof of :g:`or A B` is not accepted:
From the computational point of view, the structure of the proof of
:g:`(or A B)` in this term is needed for computing the boolean value.
-In general, if :math:`I` has type :math:`\Prop` then :math:`P` cannot have type :math:`I→Set,` because
+In general, if :math:`I` has type :math:`\Prop` then :math:`P` cannot have type :math:`I→\Set`, because
it will mean to build an informative proof of type :math:`(P~m)` doing a case
analysis over a non-computational object that will disappear in the
extracted program. But the other way is safe with respect to our
@@ -1384,11 +1384,11 @@ interpretation we can have :math:`I` a computational object and :math:`P` a
non-computational one, it just corresponds to proving a logical property
of a computational object.
-In the same spirit, elimination on :math:`P` of type :math:`I→Type` cannot be allowed
-because it trivially implies the elimination on :math:`P` of type :math:`I→ Set` by
+In the same spirit, elimination on :math:`P` of type :math:`I→\Type` cannot be allowed
+because it trivially implies the elimination on :math:`P` of type :math:`I→ \Set` by
cumulativity. It also implies that there are two proofs of the same
-property which are provably different, contradicting the proof-
-irrelevance property which is sometimes a useful axiom:
+property which are provably different, contradicting the
+proof-irrelevance property which is sometimes a useful axiom:
.. example::
@@ -1397,7 +1397,7 @@ irrelevance property which is sometimes a useful axiom:
Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y.
The elimination of an inductive definition of type :math:`\Prop` on a predicate
-:math:`P` of type :math:`I→ Type` leads to a paradox when applied to impredicative
+:math:`P` of type :math:`I→ \Type` leads to a paradox when applied to impredicative
inductive definition like the second-order existential quantifier
:g:`exProp` defined above, because it gives access to the two projections on
this type.
@@ -1413,7 +1413,7 @@ this type.
I~\kw{is an empty or singleton definition}
s ∈ \Sort
-------------------------------------
- [I:Prop|I→ s]
+ [I:\Prop|I→ s]
A *singleton definition* has only one constructor and all the
arguments of this constructor have type :math:`\Prop`. In that case, there is a
@@ -1450,7 +1450,7 @@ corresponding to the :math:`c:C` constructor.
.. math::
\begin{array}{ll}
\{c:(I~p_1\ldots p_r\ t_1 \ldots t_p)\}^P &\equiv (P~t_1\ldots ~t_p~c) \\
- \{c:\forall~x:T,C\}^P &\equiv \forall~x:T,\{(c~x):C\}^P
+ \{c:∀ x:T,~C\}^P &\equiv ∀ x:T,~\{(c~x):C\}^P
\end{array}
We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:`c`.
@@ -1469,7 +1469,7 @@ We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:
can be represented in abstract syntax as
.. math::
- \case(t,P,f 1 | f 2 )
+ \case(t,P,f_1 | f_2 )
where
@@ -1477,27 +1477,27 @@ We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:
:nowrap:
\begin{eqnarray*}
- P & = & \lambda~l~.~P^\prime\\
+ P & = & λ l.~P^\prime\\
f_1 & = & t_1\\
- f_2 & = & \lambda~(hd:\nat)~.~\lambda~(tl:\List~\nat)~.~t_2
+ f_2 & = & λ (hd:\nat).~λ (tl:\List~\nat).~t_2
\end{eqnarray*}
According to the definition:
.. math::
- \{(\kw{nil}~\nat)\}^P ≡ \{(\kw{nil}~\nat) : (\List~\nat)\}^P ≡ (P~(\kw{nil}~\nat))
+ \{(\Nil~\nat)\}^P ≡ \{(\Nil~\nat) : (\List~\nat)\}^P ≡ (P~(\Nil~\nat))
.. math::
\begin{array}{rl}
- \{(\kw{cons}~\nat)\}^P & ≡\{(\kw{cons}~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\
- & ≡∀ n:\nat, \{(\kw{cons}~\nat~n) : \List~\nat→\List~\nat)\}^P \\
- & ≡∀ n:\nat, ∀ l:\List~\nat, \{(\kw{cons}~\nat~n~l) : \List~\nat)\}^P \\
- & ≡∀ n:\nat, ∀ l:\List~\nat,(P~(\kw{cons}~\nat~n~l)).
+ \{(\cons~\nat)\}^P & ≡\{(\cons~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\
+ & ≡∀ n:\nat,~\{(\cons~\nat~n) : (\List~\nat→\List~\nat)\}^P \\
+ & ≡∀ n:\nat,~∀ l:\List~\nat,~\{(\cons~\nat~n~l) : (\List~\nat)\}^P \\
+ & ≡∀ n:\nat,~∀ l:\List~\nat,~(P~(\cons~\nat~n~l)).
\end{array}
- Given some :math:`P` then :math:`\{(\kw{nil}~\nat)\}^P` represents the expected type of :math:`f_1` ,
- and :math:`\{(\kw{cons}~\nat)\}^P` represents the expected type of :math:`f_2`.
+ Given some :math:`P` then :math:`\{(\Nil~\nat)\}^P` represents the expected type of :math:`f_1` ,
+ and :math:`\{(\cons~\nat)\}^P` represents the expected type of :math:`f_2`.
.. _Typing-rule:
@@ -1518,7 +1518,7 @@ following typing rule
E[Γ] ⊢ \case(c,P,f_1 |… |f_l ) : (P~t_1 … t_s~c)
provided :math:`I` is an inductive type in a
-definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;…;c_n :C_n ]` and
+definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;~…;~c_n :C_n ]` and
:math:`c_{p_1} … c_{p_l}` are the only constructors of :math:`I`.
@@ -1533,8 +1533,8 @@ definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;…;c_n :C_
E[Γ] ⊢ t : (\List ~\nat) \\
E[Γ] ⊢ P : B \\
[(\List ~\nat)|B] \\
- E[Γ] ⊢ f_1 : {(\kw{nil} ~\nat)}^P \\
- E[Γ] ⊢ f_2 : {(\kw{cons} ~\nat)}^P
+ E[Γ] ⊢ f_1 : \{(\Nil ~\nat)\}^P \\
+ E[Γ] ⊢ f_2 : \{(\cons ~\nat)\}^P
\end{array}
------------------------------------------------
E[Γ] ⊢ \case(t,P,f_1 |f_2 ) : (P~t)
@@ -1557,7 +1557,7 @@ The ι-contraction of this term is :math:`(f_i~a_1 … a_m )` leading to the
general reduction rule:
.. math::
- \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_n ) \triangleright_ι (f_i~a_1 … a_m )
+ \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) \triangleright_ι (f_i~a_1 … a_m )
.. _Fixpoint-definitions:
@@ -1571,14 +1571,14 @@ concrete syntax for a recursive set of mutually recursive declarations
is (with :math:`Γ_i` contexts):
.. math::
- \fix~f_1 (Γ_1 ) :A_1 :=t_1 \with … \with~f_n (Γ_n ) :A_n :=t_n
+ \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n
The terms are obtained by projections from this set of declarations
and are written
.. math::
- \fix~f_1 (Γ_1 ) :A_1 :=t_1 \with … \with~f_n (Γ_n ) :A_n :=t_n \for~f_i
+ \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n~\for~f_i
In the inference rules, we represent such a term by
@@ -1586,7 +1586,7 @@ In the inference rules, we represent such a term by
\Fix~f_i\{f_1 :A_1':=t_1' … f_n :A_n':=t_n'\}
with :math:`t_i'` (resp. :math:`A_i'`) representing the term :math:`t_i` abstracted (resp.
-generalized) with respect to the bindings in the context Γ_i , namely
+generalized) with respect to the bindings in the context :math:`Γ_i`, namely
:math:`t_i'=λ Γ_i . t_i` and :math:`A_i'=∀ Γ_i , A_i`.
@@ -1598,7 +1598,7 @@ The typing rule is the expected one for a fixpoint.
.. inference:: Fix
(E[Γ] ⊢ A_i : s_i )_{i=1… n}
- (E[Γ,f_1 :A_1 ,…,f_n :A_n ] ⊢ t_i : A_i )_{i=1… n}
+ (E[Γ;~f_1 :A_1 ;~…;~f_n :A_n ] ⊢ t_i : A_i )_{i=1… n}
-------------------------------------------------------
E[Γ] ⊢ \Fix~f_i\{f_1 :A_1 :=t_1 … f_n :A_n :=t_n \} : A_i
@@ -1614,14 +1614,14 @@ instance in the case of natural numbers, a proof of the induction
principle of type
.. math::
- ∀ P:\nat→\Prop, (P~O)→(∀ n:\nat, (P~n)→(P~(\kw{S}~n)))→ ∀ n:\nat, (P~n)
+ ∀ P:\nat→\Prop,~(P~\nO)→(∀ n:\nat,~(P~n)→(P~(\nS~n)))→ ∀ n:\nat,~(P~n)
can be represented by the term:
.. math::
\begin{array}{l}
- λ P:\nat→\Prop. λ f:(P~O). λ g:(∀ n:\nat, (P~n)→(P~(S~n))).\\
- \Fix~h\{h:∀ n:\nat, (P~n):=λ n:\nat. \case(n,P,f | λp:\nat. (g~p~(h~p)))\}
+ λ P:\nat→\Prop.~λ f:(P~\nO).~λ g:(∀ n:\nat,~(P~n)→(P~(\nS~n))).\\
+ \Fix~h\{h:∀ n:\nat,~(P~n):=λ n:\nat.~\case(n,P,f | λp:\nat.~(g~p~(h~p)))\}
\end{array}
Before accepting a fixpoint definition as being correctly typed, we
@@ -1638,7 +1638,7 @@ fixpoints is extended and becomes
where :math:`k_i` are positive integers. Each :math:`k_i` represents the index of
parameter of :math:`f_i` , on which :math:`f_i` is decreasing. Each :math:`A_i` should be a
type (reducible to a term) starting with at least :math:`k_i` products
-:math:`∀ y_1 :B_1 ,… ∀ y_{k_i} :B_{k_i} , A_i'` and :math:`B_{k_i}` an inductive type.
+:math:`∀ y_1 :B_1 ,~… ∀ y_{k_i} :B_{k_i} ,~A_i'` and :math:`B_{k_i}` an inductive type.
Now in the definition :math:`t_i`, if :math:`f_j` occurs then it should be applied to
at least :math:`k_j` arguments and the :math:`k_j`-th argument should be
@@ -1648,23 +1648,23 @@ The definition of being structurally smaller is a bit technical. One
needs first to define the notion of *recursive arguments of a
constructor*. For an inductive definition :math:`\ind{r}{Γ_I}{Γ_C}`, if the
type of a constructor :math:`c` has the form
-:math:`∀ p_1 :P_1 ,… ∀ p_r :P_r, ∀ x_1:T_1, … ∀ x_r :T_r, (I_j~p_1 … p_r~t_1 … t_s )`,
+:math:`∀ p_1 :P_1 ,~… ∀ p_r :P_r,~∀ x_1:T_1,~… ∀ x_r :T_r,~(I_j~p_1 … p_r~t_1 … t_s )`,
then the recursive
arguments will correspond to :math:`T_i` in which one of the :math:`I_l` occurs.
The main rules for being structurally smaller are the following.
Given a variable :math:`y` of an inductively defined type in a declaration
-:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;…;I_k :A_k]`, and :math:`Γ_C` is
-:math:`[c_1 :C_1 ;…;c_n :C_n ]`, the terms structurally smaller than :math:`y` are:
+:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;~…;~I_k :A_k]`, and :math:`Γ_C` is
+:math:`[c_1 :C_1 ;~…;~c_n :C_n ]`, the terms structurally smaller than :math:`y` are:
-+ :math:`(t~u)` and :math:`λ x:u . t` when :math:`t` is structurally smaller than :math:`y`.
++ :math:`(t~u)` and :math:`λ x:U .~t` when :math:`t` is structurally smaller than :math:`y`.
+ :math:`\case(c,P,f_1 … f_n)` when each :math:`f_i` is structurally smaller than :math:`y`.
If :math:`c` is :math:`y` or is structurally smaller than :math:`y`, its type is an inductive
definition :math:`I_p` part of the inductive declaration corresponding to :math:`y`.
Each :math:`f_i` corresponds to a type of constructor
- :math:`C_q ≡ ∀ p_1 :P_1 ,…,∀ p_r :P_r , ∀ y_1 :B_1 , … ∀ y_k :B_k , (I~a_1 … a_k )`
- and can consequently be written :math:`λ y_1 :B_1' . … λ y_k :B_k'. g_i`. (:math:`B_i'` is
+ :math:`C_q ≡ ∀ p_1 :P_1 ,~…,∀ p_r :P_r ,~∀ y_1 :B_1 ,~… ∀ y_k :B_k ,~(I~a_1 … a_k )`
+ and can consequently be written :math:`λ y_1 :B_1' .~… λ y_k :B_k'.~g_i`. (:math:`B_i'` is
obtained from :math:`B_i` by substituting parameters for variables) the variables
:math:`y_j` occurring in :math:`g_i` corresponding to recursive arguments :math:`B_i` (the
ones in which one of the :math:`I_l` occurs) are structurally smaller than y.
@@ -1708,7 +1708,7 @@ Let :math:`F` be the set of declarations:
The reduction for fixpoints is:
.. math::
- (\Fix~f_i \{F\} a_1 …a_{k_i}) \triangleright_ι \subst{t_i}{f_k}{\Fix~f_k \{F\}}_{k=1… n} ~a_1 … a_{k_i}
+ (\Fix~f_i \{F\}~a_1 …a_{k_i}) ~\triangleright_ι~ \subst{t_i}{f_k}{\Fix~f_k \{F\}}_{k=1… n} ~a_1 … a_{k_i}
when :math:`a_{k_i}` starts with a constructor. This last restriction is needed
in order to keep strong normalization and corresponds to the reduction
@@ -1718,13 +1718,11 @@ possible:
.. math::
:nowrap:
- {\def\plus{\mathsf{plus}}
- \def\tri{\triangleright_\iota}
- \begin{eqnarray*}
- \plus~(\nS~(\nS~\nO))~(\nS~\nO) & \tri & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\
- & \tri & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\
- & \tri & \nS~(\nS~(\nS~\nO))\\
- \end{eqnarray*}}
+ \begin{eqnarray*}
+ \plus~(\nS~(\nS~\nO))~(\nS~\nO)~& \trii & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\
+ & \trii & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\
+ & \trii & \nS~(\nS~(\nS~\nO))\\
+ \end{eqnarray*}
.. _Mutual-induction:
@@ -1754,9 +1752,9 @@ reference to the global declaration in the subsequent global
environment and local context by explicitly applying this constant to
the constant :math:`c'`.
-Below, if :math:`Γ` is a context of the form :math:`[y_1 :A_1 ;…;y_n :A_n]`, we write
-:math:`∀x:U,\subst{Γ}{c}{x}` to mean
-:math:`[y_1 :∀ x:U,\subst{A_1}{c}{x};…;y_n :∀ x:U,\subst{A_n}{c}{x}]`
+Below, if :math:`Γ` is a context of the form :math:`[y_1 :A_1 ;~…;~y_n :A_n]`, we write
+:math:`∀x:U,~\subst{Γ}{c}{x}` to mean
+:math:`[y_1 :∀ x:U,~\subst{A_1}{c}{x};~…;~y_n :∀ x:U,~\subst{A_n}{c}{x}]`
and :math:`\subst{E}{|Γ|}{|Γ|c}` to mean the parallel substitution
:math:`E\{y_1 /(y_1~c)\}…\{y_n/(y_n~c)\}`.
@@ -1766,25 +1764,25 @@ and :math:`\subst{E}{|Γ|}{|Γ|c}` to mean the parallel substitution
**First abstracting property:**
.. math::
- \frac{\WF{E;c:U;E′;c′:=t:T;E″}{Γ}}
- {\WF{E;c:U;E′;c′:=λ x:U. \subst{t}{c}{x}:∀x:U,\subst{T}{c}{x};\subst{E″}{c′}{(c′~c)}}
- {\subst{Γ}{c}{(c~c′)}}}
+ \frac{\WF{E;~c:U;~E′;~c′:=t:T;~E″}{Γ}}
+ {\WF{E;~c:U;~E′;~c′:=λ x:U.~\subst{t}{c}{x}:∀x:U,~\subst{T}{c}{x};~\subst{E″}{c′}{(c′~c)}}
+ {\subst{Γ}{c′}{(c′~c)}}}
.. math::
- \frac{\WF{E;c:U;E′;c′:T;E″}{Γ}}
- {\WF{E;c:U;E′;c′:∀ x:U,\subst{T}{c}{x};\subst{E″}{c′}{(c′~c)}}{Γ{c/(c~c′)}}}
+ \frac{\WF{E;~c:U;~E′;~c′:T;~E″}{Γ}}
+ {\WF{E;~c:U;~E′;~c′:∀ x:U,~\subst{T}{c}{x};~\subst{E″}{c′}{(c′~c)}}{\subst{Γ}{c′}{(c′~c)}}}
.. math::
- \frac{\WF{E;c:U;E′;\ind{p}{Γ_I}{Γ_C};E″}{Γ}}
- {\WFTWOLINES{E;c:U;E′;\ind{p+1}{∀ x:U,\subst{Γ_I}{c}{x}}{∀ x:U,\subst{Γ_C}{c}{x}};
- \subst{E″}{|Γ_I ,Γ_C |}{|Γ_I ,Γ_C | c}}
- {\subst{Γ}{|Γ_I ,Γ_C|}{|Γ_I ,Γ_C | c}}}
+ \frac{\WF{E;~c:U;~E′;~\ind{p}{Γ_I}{Γ_C};~E″}{Γ}}
+ {\WFTWOLINES{E;~c:U;~E′;~\ind{p+1}{∀ x:U,~\subst{Γ_I}{c}{x}}{∀ x:U,~\subst{Γ_C}{c}{x}};~
+ \subst{E″}{|Γ_I ;Γ_C |}{|Γ_I ;Γ_C | c}}
+ {\subst{Γ}{|Γ_I ;Γ_C|}{|Γ_I ;Γ_C | c}}}
One can similarly modify a global declaration by generalizing it over
a previously defined constant :math:`c′`. Below, if :math:`Γ` is a context of the form
-:math:`[y_1 :A_1 ;…;y_n :A_n]`, we write :math:`\subst{Γ}{c}{u}` to mean
-:math:`[y_1 :\subst{A_1} {c}{u};…;y_n:\subst{A_n} {c}{u}]`.
+:math:`[y_1 :A_1 ;~…;~y_n :A_n]`, we write :math:`\subst{Γ}{c}{u}` to mean
+:math:`[y_1 :\subst{A_1} {c}{u};~…;~y_n:\subst{A_n} {c}{u}]`.
.. _Second-abstracting-property:
@@ -1792,16 +1790,16 @@ a previously defined constant :math:`c′`. Below, if :math:`Γ` is a context of
**Second abstracting property:**
.. math::
- \frac{\WF{E;c:=u:U;E′;c′:=t:T;E″}{Γ}}
- {\WF{E;c:=u:U;E′;c′:=(\letin{x}{u:U}{\subst{t}{c}{x}}):\subst{T}{c}{u};E″}{Γ}}
+ \frac{\WF{E;~c:=u:U;~E′;~c′:=t:T;~E″}{Γ}}
+ {\WF{E;~c:=u:U;~E′;~c′:=(\letin{x}{u:U}{\subst{t}{c}{x}}):\subst{T}{c}{u};~E″}{Γ}}
.. math::
- \frac{\WF{E;c:=u:U;E′;c′:T;E″}{Γ}}
- {\WF{E;c:=u:U;E′;c′:\subst{T}{c}{u};E″}{Γ}}
+ \frac{\WF{E;~c:=u:U;~E′;~c′:T;~E″}{Γ}}
+ {\WF{E;~c:=u:U;~E′;~c′:\subst{T}{c}{u};~E″}{Γ}}
.. math::
- \frac{\WF{E;c:=u:U;E′;\ind{p}{Γ_I}{Γ_C};E″}{Γ}}
- {\WF{E;c:=u:U;E′;\ind{p}{\subst{Γ_I}{c}{u}}{\subst{Γ_C}{c}{u}};E″}{Γ}}
+ \frac{\WF{E;~c:=u:U;~E′;~\ind{p}{Γ_I}{Γ_C};~E″}{Γ}}
+ {\WF{E;~c:=u:U;~E′;~\ind{p}{\subst{Γ_I}{c}{u}}{\subst{Γ_C}{c}{u}};~E″}{Γ}}
.. _Pruning-the-local-context:
@@ -1816,7 +1814,7 @@ One can consequently derive the following property.
.. inference:: First pruning property:
- \WF{E;c:U;E′}{Γ}
+ \WF{E;~c:U;~E′}{Γ}
c~\kw{does not occur in}~E′~\kw{and}~Γ
--------------------------------------
\WF{E;E′}{Γ}
@@ -1826,7 +1824,7 @@ One can consequently derive the following property.
.. inference:: Second pruning property:
- \WF{E;c:=u:U;E′}{Γ}
+ \WF{E;~c:=u:U;~E′}{Γ}
c~\kw{does not occur in}~E′~\kw{and}~Γ
--------------------------------------
\WF{E;E′}{Γ}
@@ -1867,10 +1865,10 @@ in the sort :math:`\Set`, which is extended to a domain in any sort:
.. inference:: ProdImp
E[Γ] ⊢ T : s
- s ∈ {\Sort}
- E[Γ::(x:T)] ⊢ U : Set
+ s ∈ \Sort
+ E[Γ::(x:T)] ⊢ U : \Set
---------------------
- E[Γ] ⊢ ∀ x:T,U : Set
+ E[Γ] ⊢ ∀ x:T,~U : \Set
This extension has consequences on the inductive definitions which are
allowed. In the impredicative system, one can build so-called *large
@@ -1885,15 +1883,15 @@ impredicative system for sort :math:`\Set` become:
.. inference:: Set1
- s ∈ \{Prop, Set\}
+ s ∈ \{\Prop, \Set\}
-----------------
- [I:Set|I→ s]
+ [I:\Set|I→ s]
.. inference:: Set2
I~\kw{is a small inductive definition}
s ∈ \{\Type(i)\}
----------------
- [I:Set|I→ s]
+ [I:\Set|I→ s]
diff --git a/doc/sphinx/language/coq-library.rst b/doc/sphinx/language/coq-library.rst
index 10650af1d1..b82b3b0e80 100644
--- a/doc/sphinx/language/coq-library.rst
+++ b/doc/sphinx/language/coq-library.rst
@@ -104,18 +104,18 @@ subclass :token:`form` of the syntactic class :token:`term`. The syntax of
a nice last column. Or even better, find a proper way to do this!
.. productionlist::
- form : True (True)
- : | False (False)
- : | ~ `form` (not)
- : | `form` /\ `form` (and)
- : | `form` \/ `form` (or)
- : | `form` -> `form` (primitive implication)
- : | `form` <-> `form` (iff)
- : | forall `ident` : `type`, `form` (primitive for all)
- : | exists `ident` [: `specif`], `form` (ex)
- : | exists2 `ident` [: `specif`], `form` & `form` (ex2)
- : | `term` = `term` (eq)
- : | `term` = `term` :> `specif` (eq)
+ form : True (True)
+ : False (False)
+ : ~ `form` (not)
+ : `form` /\ `form` (and)
+ : `form` \/ `form` (or)
+ : `form` -> `form` (primitive implication)
+ : `form` <-> `form` (iff)
+ : forall `ident` : `type`, `form` (primitive for all)
+ : exists `ident` [: `specif`], `form` (ex)
+ : exists2 `ident` [: `specif`], `form` & `form` (ex2)
+ : `term` = `term` (eq)
+ : `term` = `term` :> `specif` (eq)
.. note::
@@ -287,13 +287,13 @@ the next section :ref:`specification`):
.. productionlist::
specif : `specif` * `specif` (prod)
- : | `specif` + `specif` (sum)
- : | `specif` + { `specif` } (sumor)
- : | { `specif` } + { `specif` } (sumbool)
- : | { `ident` : `specif` | `form` } (sig)
- : | { `ident` : `specif` | `form` & `form` } (sig2)
- : | { `ident` : `specif` & `specif` } (sigT)
- : | { `ident` : `specif` & `specif` & `specif` } (sigT2)
+ : `specif` + `specif` (sum)
+ : `specif` + { `specif` } (sumor)
+ : { `specif` } + { `specif` } (sumbool)
+ : { `ident` : `specif` | `form` } (sig)
+ : { `ident` : `specif` | `form` & `form` } (sig2)
+ : { `ident` : `specif` & `specif` } (sigT)
+ : { `ident` : `specif` & `specif` & `specif` } (sigT2)
term : (`term`, `term`) (pair)
diff --git a/doc/sphinx/language/gallina-extensions.rst b/doc/sphinx/language/gallina-extensions.rst
index 376a6b8eed..50a56f1d51 100644
--- a/doc/sphinx/language/gallina-extensions.rst
+++ b/doc/sphinx/language/gallina-extensions.rst
@@ -25,7 +25,7 @@ expressions. In this sense, the :cmd:`Record` construction allows defining
record_keyword : Record | Inductive | CoInductive
record_body : `ident` [ `binders` ] [: `sort` ] := [ `ident` ] { [ `field` ; … ; `field` ] }.
field : `ident` [ `binders` ] : `type` [ where `notation` ]
- : | `ident` [ `binders` ] [: `type` ] := `term`
+ : `ident` [ `binders` ] [: `type` ] := `term`
.. cmd:: Record @ident @binders {? : @sort} := {? @ident} { {*; @ident @binders : @type } }
@@ -165,8 +165,8 @@ available:
.. productionlist:: terms
projection : `term` `.` ( `qualid` )
- : | `term` `.` ( `qualid` `arg` … `arg` )
- : | `term` `.` ( @`qualid` `term` … `term` )
+ : `term` `.` ( `qualid` `arg` … `arg` )
+ : `term` `.` ( @`qualid` `term` … `term` )
Syntax of Record projections
@@ -234,7 +234,8 @@ Primitive Projections
extended the Calculus of Inductive Constructions with a new binary
term constructor `r.(p)` representing a primitive projection `p` applied
to a record object `r` (i.e., primitive projections are always applied).
- Even if the record type has parameters, these do not appear at
+ Even if the record type has parameters, these do not appear
+ in the internal representation of
applications of the projection, considerably reducing the sizes of
terms when manipulating parameterized records and type checking time.
On the user level, primitive projections can be used as a replacement
@@ -818,14 +819,14 @@ together, as well as a means of massive abstraction.
.. productionlist:: modules
module_type : `qualid`
- : | `module_type` with Definition `qualid` := `term`
- : | `module_type` with Module `qualid` := `qualid`
- : | `qualid` `qualid` … `qualid`
- : | !`qualid` `qualid` … `qualid`
+ : `module_type` with Definition `qualid` := `term`
+ : `module_type` with Module `qualid` := `qualid`
+ : `qualid` `qualid` … `qualid`
+ : !`qualid` `qualid` … `qualid`
module_binding : ( [Import|Export] `ident` … `ident` : `module_type` )
module_bindings : `module_binding` … `module_binding`
module_expression : `qualid` … `qualid`
- : | !`qualid` … `qualid`
+ : !`qualid` … `qualid`
Syntax of modules
@@ -1814,10 +1815,10 @@ This syntax extension is given in the following grammar:
.. productionlist:: explicit_apps
term : @ `qualid` `term` … `term`
- : | @ `qualid`
- : | `qualid` `argument` … `argument`
+ : @ `qualid`
+ : `qualid` `argument` … `argument`
argument : `term`
- : | (`ident` := `term`)
+ : (`ident` := `term`)
Syntax for explicitly giving implicit arguments
diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst
index 8fa631174f..5ecf007eff 100644
--- a/doc/sphinx/language/gallina-specification-language.rst
+++ b/doc/sphinx/language/gallina-specification-language.rst
@@ -127,43 +127,43 @@ is described in Chapter :ref:`syntaxextensionsandinterpretationscopes`.
.. productionlist:: coq
term : forall `binders` , `term`
- : | fun `binders` => `term`
- : | fix `fix_bodies`
- : | cofix `cofix_bodies`
- : | let `ident` [`binders`] [: `term`] := `term` in `term`
- : | let fix `fix_body` in `term`
- : | let cofix `cofix_body` in `term`
- : | let ( [`name` , … , `name`] ) [`dep_ret_type`] := `term` in `term`
- : | let ' `pattern` [in `term`] := `term` [`return_type`] in `term`
- : | if `term` [`dep_ret_type`] then `term` else `term`
- : | `term` : `term`
- : | `term` <: `term`
- : | `term` :>
- : | `term` -> `term`
- : | `term` `arg` … `arg`
- : | @ `qualid` [`term` … `term`]
- : | `term` % `ident`
- : | match `match_item` , … , `match_item` [`return_type`] with
+ : fun `binders` => `term`
+ : fix `fix_bodies`
+ : cofix `cofix_bodies`
+ : let `ident` [`binders`] [: `term`] := `term` in `term`
+ : let fix `fix_body` in `term`
+ : let cofix `cofix_body` in `term`
+ : let ( [`name` , … , `name`] ) [`dep_ret_type`] := `term` in `term`
+ : let ' `pattern` [in `term`] := `term` [`return_type`] in `term`
+ : if `term` [`dep_ret_type`] then `term` else `term`
+ : `term` : `term`
+ : `term` <: `term`
+ : `term` :>
+ : `term` -> `term`
+ : `term` `arg` … `arg`
+ : @ `qualid` [`term` … `term`]
+ : `term` % `ident`
+ : match `match_item` , … , `match_item` [`return_type`] with
: [[|] `equation` | … | `equation`] end
- : | `qualid`
- : | `sort`
- : | `num`
- : | _
- : | ( `term` )
+ : `qualid`
+ : `sort`
+ : `num`
+ : _
+ : ( `term` )
arg : `term`
- : | ( `ident` := `term` )
+ : ( `ident` := `term` )
binders : `binder` … `binder`
binder : `name`
- : | ( `name` … `name` : `term` )
- : | ( `name` [: `term`] := `term` )
- : | ' `pattern`
+ : ( `name` … `name` : `term` )
+ : ( `name` [: `term`] := `term` )
+ : ' `pattern`
name : `ident` | _
qualid : `ident` | `qualid` `access_ident`
sort : Prop | Set | Type
fix_bodies : `fix_body`
- : | `fix_body` with `fix_body` with … with `fix_body` for `ident`
+ : `fix_body` with `fix_body` with … with `fix_body` for `ident`
cofix_bodies : `cofix_body`
- : | `cofix_body` with `cofix_body` with … with `cofix_body` for `ident`
+ : `cofix_body` with `cofix_body` with … with `cofix_body` for `ident`
fix_body : `ident` `binders` [`annotation`] [: `term`] := `term`
cofix_body : `ident` [`binders`] [: `term`] := `term`
annotation : { struct `ident` }
@@ -173,13 +173,13 @@ is described in Chapter :ref:`syntaxextensionsandinterpretationscopes`.
equation : `mult_pattern` | … | `mult_pattern` => `term`
mult_pattern : `pattern` , … , `pattern`
pattern : `qualid` `pattern` … `pattern`
- : | @ `qualid` `pattern` … `pattern`
- : | `pattern` as `ident`
- : | `pattern` % `ident`
- : | `qualid`
- : | _
- : | `num`
- : | ( `or_pattern` , … , `or_pattern` )
+ : @ `qualid` `pattern` … `pattern`
+ : `pattern` as `ident`
+ : `pattern` % `ident`
+ : `qualid`
+ : _
+ : `num`
+ : ( `or_pattern` , … , `or_pattern` )
or_pattern : `pattern` | … | `pattern`
@@ -524,38 +524,38 @@ The Vernacular
.. productionlist:: coq
decorated-sentence : [ `decoration` … `decoration` ] `sentence`
sentence : `assumption`
- : | `definition`
- : | `inductive`
- : | `fixpoint`
- : | `assertion` `proof`
+ : `definition`
+ : `inductive`
+ : `fixpoint`
+ : `assertion` `proof`
assumption : `assumption_keyword` `assums`.
assumption_keyword : Axiom | Conjecture
- : | Parameter | Parameters
- : | Variable | Variables
- : | Hypothesis | Hypotheses
+ : Parameter | Parameters
+ : Variable | Variables
+ : Hypothesis | Hypotheses
assums : `ident` … `ident` : `term`
- : | ( `ident` … `ident` : `term` ) … ( `ident` … `ident` : `term` )
+ : ( `ident` … `ident` : `term` ) … ( `ident` … `ident` : `term` )
definition : [Local] Definition `ident` [`binders`] [: `term`] := `term` .
- : | Let `ident` [`binders`] [: `term`] := `term` .
+ : Let `ident` [`binders`] [: `term`] := `term` .
inductive : Inductive `ind_body` with … with `ind_body` .
- : | CoInductive `ind_body` with … with `ind_body` .
+ : CoInductive `ind_body` with … with `ind_body` .
ind_body : `ident` [`binders`] : `term` :=
: [[|] `ident` [`binders`] [:`term`] | … | `ident` [`binders`] [:`term`]]
fixpoint : Fixpoint `fix_body` with … with `fix_body` .
- : | CoFixpoint `cofix_body` with … with `cofix_body` .
+ : CoFixpoint `cofix_body` with … with `cofix_body` .
assertion : `assertion_keyword` `ident` [`binders`] : `term` .
assertion_keyword : Theorem | Lemma
- : | Remark | Fact
- : | Corollary | Proposition
- : | Definition | Example
+ : Remark | Fact
+ : Corollary | Proposition
+ : Definition | Example
proof : Proof . … Qed .
- : | Proof . … Defined .
- : | Proof . … Admitted .
+ : Proof . … Defined .
+ : Proof . … Admitted .
decoration : #[ `attributes` ]
attributes : [`attribute`, … , `attribute`]
attribute : `ident`
- :| `ident` = `string`
- :| `ident` ( `attributes` )
+ : `ident` = `string`
+ : `ident` ( `attributes` )
.. todo:: This use of … in this grammar is inconsistent
What about removing the proof part of this grammar from this chapter
diff --git a/doc/sphinx/practical-tools/coq-commands.rst b/doc/sphinx/practical-tools/coq-commands.rst
index 9bc67147f7..1b4d2315aa 100644
--- a/doc/sphinx/practical-tools/coq-commands.rst
+++ b/doc/sphinx/practical-tools/coq-commands.rst
@@ -163,14 +163,14 @@ and ``coqtop``, unless stated otherwise:
is equivalent to runningRequire dirpath.
:-require dirpath: Load |Coq| compiled library dirpath and import it.
This is equivalent to running Require Import dirpath.
-:-batch: Exit just after argument parsing. Available for `coqtop` only.
-:-compile *file.v*: Compile file *file.v* into *file.vo*. This option
+:-batch: Exit just after argument parsing. Available for ``coqtop`` only.
+:-compile *file.v*: Deprecated; use ``coqc`` instead. Compile file *file.v* into *file.vo*. This option
implies -batch (exit just after argument parsing). It is available only
- for `coqtop`, as this behavior is the purpose of `coqc`.
-:-compile-verbose *file.v*: Same as -compile but also output the
+ for `coqtop`, as this behavior is the purpose of ``coqc``.
+:-compile-verbose *file.v*: Deprecated. Use ``coqc -verbose``. Same as -compile but also output the
content of *file.v* as it is compiled.
:-verbose: Output the content of the input file as it is compiled.
- This option is available for `coqc` only; it is the counterpart of
+ This option is available for ``coqc`` only; it is the counterpart of
-compile-verbose.
:-w (all|none|w₁,…,wₙ): Configure the display of warnings. This
option expects all, none or a comma-separated list of warning names or
@@ -211,11 +211,11 @@ and ``coqtop``, unless stated otherwise:
(to be used by coqdoc, see :ref:`coqdoc`). By default, if *file.v* is being
compiled, *file.glob* is used.
:-no-glob: Disable the dumping of references for global names.
-:-image *file*: Set the binary image to be used by `coqc` to be *file*
+:-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
- used by `coqc`. It is equivalent to doing export COQBIN= *directory*
- before launching `coqc`.
+ 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
libraries, then exit.
diff --git a/doc/sphinx/proof-engine/ltac.rst b/doc/sphinx/proof-engine/ltac.rst
index 1071682ead..442077616f 100644
--- a/doc/sphinx/proof-engine/ltac.rst
+++ b/doc/sphinx/proof-engine/ltac.rst
@@ -41,117 +41,121 @@ mode but it can also be used in toplevel definitions as shown below.
.. note::
- - The infix tacticals “… \|\| …”, “… + …”, and “… ; …” are associative.
+ - The infix tacticals  ``… || …`` ,  ``… + …`` , and  ``… ; …``  are associative.
- - In :token:`tacarg`, there is an overlap between qualid as a direct tactic
- argument and :token:`qualid` as a particular case of term. The resolution is
- done by first looking for a reference of the tactic language and if
- it fails, for a reference to a term. To force the resolution as a
- reference of the tactic language, use the form :g:`ltac:(@qualid)`. To
- force the resolution as a reference to a term, use the syntax
- :g:`(@qualid)`.
+ .. example::
- - As shown by the figure, tactical ``\|\|`` binds more than the prefix
- tacticals try, repeat, do and abstract which themselves bind more
- than the postfix tactical “… ;[ … ]” which binds more than “… ; …”.
+ If you want that :n:`@tactic__2; @tactic__3` be fully run on the first
+ subgoal generated by :n:`@tactic__1`, before running on the other
+ subgoals, then you should not write
+ :n:`@tactic__1; (@tactic__2; @tactic__3)` but rather
+ :n:`@tactic__1; [> @tactic__2; @tactic__3 .. ]`.
- For instance
+ - In :token:`tacarg`, there is an overlap between :token:`qualid` as a
+ direct tactic argument and :token:`qualid` as a particular case of
+ :token:`term`. The resolution is done by first looking for a reference
+ of the tactic language and if it fails, for a reference to a term.
+ To force the resolution as a reference of the tactic language, use the
+ form :n:`ltac:(@qualid)`. To force the resolution as a reference to a
+ term, use the syntax :n:`(@qualid)`.
- .. coqtop:: in
+ - As shown by the figure, tactical  ``… || …``  binds more than the prefix
+ tacticals :tacn:`try`, :tacn:`repeat`, :tacn:`do` and :tacn:`abstract`
+ which themselves bind more than the postfix tactical  ``… ;[ … ]`` 
+ which binds at the same level as  ``… ; …`` .
- try repeat tac1 || tac2; tac3; [tac31 | ... | tac3n]; tac4.
+ .. example::
- is understood as
+ :n:`try repeat @tactic__1 || @tactic__2; @tactic__3; [ {+| @tactic } ]; @tactic__4`
- .. coqtop:: in
+ is understood as:
- try (repeat (tac1 || tac2));
- ((tac3; [tac31 | ... | tac3n]); tac4).
+ :n:`((try (repeat (@tactic__1 || @tactic__2)); @tactic__3); [ {+| @tactic } ]); @tactic__4`
.. productionlist:: coq
expr : `expr` ; `expr`
- : | [> `expr` | ... | `expr` ]
- : | `expr` ; [ `expr` | ... | `expr` ]
- : | `tacexpr3`
- tacexpr3 : do (`natural` | `ident`) tacexpr3
- : | progress `tacexpr3`
- : | repeat `tacexpr3`
- : | try `tacexpr3`
- : | once `tacexpr3`
- : | exactly_once `tacexpr3`
- : | timeout (`natural` | `ident`) `tacexpr3`
- : | time [`string`] `tacexpr3`
- : | only `selector`: `tacexpr3`
- : | `tacexpr2`
+ : [> `expr` | ... | `expr` ]
+ : `expr` ; [ `expr` | ... | `expr` ]
+ : `tacexpr3`
+ tacexpr3 : do (`natural` | `ident`) `tacexpr3`
+ : progress `tacexpr3`
+ : repeat `tacexpr3`
+ : try `tacexpr3`
+ : once `tacexpr3`
+ : exactly_once `tacexpr3`
+ : timeout (`natural` | `ident`) `tacexpr3`
+ : time [`string`] `tacexpr3`
+ : only `selector`: `tacexpr3`
+ : `tacexpr2`
tacexpr2 : `tacexpr1` || `tacexpr3`
- : | `tacexpr1` + `tacexpr3`
- : | tryif `tacexpr1` then `tacexpr1` else `tacexpr1`
- : | `tacexpr1`
+ : `tacexpr1` + `tacexpr3`
+ : tryif `tacexpr1` then `tacexpr1` else `tacexpr1`
+ : `tacexpr1`
tacexpr1 : fun `name` ... `name` => `atom`
- : | let [rec] `let_clause` with ... with `let_clause` in `atom`
- : | match goal with `context_rule` | ... | `context_rule` end
- : | match reverse goal with `context_rule` | ... | `context_rule` end
- : | match `expr` with `match_rule` | ... | `match_rule` end
- : | lazymatch goal with `context_rule` | ... | `context_rule` end
- : | lazymatch reverse goal with `context_rule` | ... | `context_rule` end
- : | lazymatch `expr` with `match_rule` | ... | `match_rule` end
- : | multimatch goal with `context_rule` | ... | `context_rule` end
- : | multimatch reverse goal with `context_rule` | ... | `context_rule` end
- : | multimatch `expr` with `match_rule` | ... | `match_rule` end
- : | abstract `atom`
- : | abstract `atom` using `ident`
- : | first [ `expr` | ... | `expr` ]
- : | solve [ `expr` | ... | `expr` ]
- : | idtac [ `message_token` ... `message_token`]
- : | fail [`natural`] [`message_token` ... `message_token`]
- : | fresh [ `component` … `component` ]
- : | context `ident` [`term`]
- : | eval `redexpr` in `term`
- : | type of `term`
- : | constr : `term`
- : | uconstr : `term`
- : | type_term `term`
- : | numgoals
- : | guard `test`
- : | assert_fails `tacexpr3`
- : | assert_succeeds `tacexpr3`
- : | `atomic_tactic`
- : | `qualid` `tacarg` ... `tacarg`
- : | `atom`
+ : let [rec] `let_clause` with ... with `let_clause` in `atom`
+ : match goal with `context_rule` | ... | `context_rule` end
+ : match reverse goal with `context_rule` | ... | `context_rule` end
+ : match `expr` with `match_rule` | ... | `match_rule` end
+ : lazymatch goal with `context_rule` | ... | `context_rule` end
+ : lazymatch reverse goal with `context_rule` | ... | `context_rule` end
+ : lazymatch `expr` with `match_rule` | ... | `match_rule` end
+ : multimatch goal with `context_rule` | ... | `context_rule` end
+ : multimatch reverse goal with `context_rule` | ... | `context_rule` end
+ : multimatch `expr` with `match_rule` | ... | `match_rule` end
+ : abstract `atom`
+ : abstract `atom` using `ident`
+ : first [ `expr` | ... | `expr` ]
+ : solve [ `expr` | ... | `expr` ]
+ : idtac [ `message_token` ... `message_token`]
+ : fail [`natural`] [`message_token` ... `message_token`]
+ : fresh [ `component` … `component` ]
+ : context `ident` [`term`]
+ : eval `redexpr` in `term`
+ : type of `term`
+ : constr : `term`
+ : uconstr : `term`
+ : type_term `term`
+ : numgoals
+ : guard `test`
+ : assert_fails `tacexpr3`
+ : assert_succeeds `tacexpr3`
+ : `atomic_tactic`
+ : `qualid` `tacarg` ... `tacarg`
+ : `atom`
atom : `qualid`
- : | ()
- : | `integer`
- : | ( `expr` )
+ : ()
+ : `integer`
+ : ( `expr` )
component : `string` | `qualid`
message_token : `string` | `ident` | `integer`
tacarg : `qualid`
- : | ()
- : | ltac : `atom`
- : | `term`
+ : ()
+ : ltac : `atom`
+ : `term`
let_clause : `ident` [`name` ... `name`] := `expr`
context_rule : `context_hyp`, ..., `context_hyp` |- `cpattern` => `expr`
- : | `cpattern` => `expr`
- : | |- `cpattern` => `expr`
- : | _ => `expr`
+ : `cpattern` => `expr`
+ : |- `cpattern` => `expr`
+ : _ => `expr`
context_hyp : `name` : `cpattern`
- : | `name` := `cpattern` [: `cpattern`]
+ : `name` := `cpattern` [: `cpattern`]
match_rule : `cpattern` => `expr`
- : | context [ident] [ `cpattern` ] => `expr`
- : | _ => `expr`
+ : context [`ident`] [ `cpattern` ] => `expr`
+ : _ => `expr`
test : `integer` = `integer`
- : | `integer` (< | <= | > | >=) `integer`
+ : `integer` (< | <= | > | >=) `integer`
selector : [`ident`]
- : | `integer`
- : | (`integer` | `integer` - `integer`), ..., (`integer` | `integer` - `integer`)
+ : `integer`
+ : (`integer` | `integer` - `integer`), ..., (`integer` | `integer` - `integer`)
toplevel_selector : `selector`
- : | all
- : | par
- : | !
+ : all
+ : par
+ : !
.. productionlist:: coq
top : [Local] Ltac `ltac_def` with ... with `ltac_def`
ltac_def : `ident` [`ident` ... `ident`] := `expr`
- : | `qualid` [`ident` ... `ident`] ::= `expr`
+ : `qualid` [`ident` ... `ident`] ::= `expr`
.. _ltac-semantics:
diff --git a/doc/sphinx/proof-engine/ssreflect-proof-language.rst b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
index 92bd4dbd1d..483dbd311d 100644
--- a/doc/sphinx/proof-engine/ssreflect-proof-language.rst
+++ b/doc/sphinx/proof-engine/ssreflect-proof-language.rst
@@ -1445,6 +1445,16 @@ section constant.
If tactic is ``move`` or ``case`` and an equation :token:`ident` is given, then clear
(step 3) for :token:`d_item` is suppressed (see section :ref:`generation_of_equations_ssr`).
+Intro patterns (see section :ref:`introduction_ssr`)
+and the ``rewrite`` tactic (see section :ref:`rewriting_ssr`)
+let one place a :token:`clear_switch` in the middle of other items
+(namely identifiers, views and rewrite rules). This can trigger the
+addition of proof context items to the ones being explicitly
+cleared, and in turn this can result in clear errors (e.g. if the
+context item automatically added occurs in the goal). The
+relevant sections describe ways to avoid the unintended clear of
+context items.
+
Matching for apply and exact
````````````````````````````
@@ -1572,6 +1582,9 @@ The :token:`i_pattern`\s can be seen as a variant of *intro patterns*
(see :tacn:`intros`:) each performs an introduction operation, i.e., pops some
variables or assumptions from the goal.
+Simplification items
+`````````````````````
+
An :token:`s_item` can simplify the set of subgoals or the subgoals themselves:
+ ``//`` removes all the “trivial” subgoals that can be resolved by the
@@ -1583,18 +1596,32 @@ An :token:`s_item` can simplify the set of subgoals or the subgoals themselves:
``/= //``, i.e., ``simpl; try done``.
-When an :token:`s_item` bears a :token:`clear_switch`, then the
+When an :token:`s_item` immediately precedes a :token:`clear_switch`, then the
:token:`clear_switch` is executed
*after* the :token:`s_item`, e.g., ``{IHn}//`` will solve some subgoals,
possibly using the fact ``IHn``, and will erase ``IHn`` from the context
of the remaining subgoals.
+Views
+`````
+
The first entry in the :token:`i_view` grammar rule, :n:`/@term`,
represents a view (see section :ref:`views_and_reflection_ssr`).
It interprets the top of the stack with the view :token:`term`.
-It is equivalent to ``move/term``. The optional flag ``{}`` can
-be used to signal that the :token:`term`, when it is a context entry,
-has to be cleared.
+It is equivalent to :n:`move/@term`.
+
+A :token:`clear_switch` that immediately precedes an :token:`i_view`
+is complemented with the name of the view if an only if the :token:`i_view`
+is a simple proof context entry [#10]_.
+E.g. ``{}/v`` is equivalent to ``/v{v}``.
+This behavior can be avoided by separating the :token:`clear_switch`
+from the :token:`i_view` with the ``-`` intro pattern or by putting
+parentheses around the view.
+
+A :token:`clear_switch` that immediately precedes an :token:`i_view`
+is executed after the view application.
+
+
If the next :token:`i_item` is a view, then the view is
applied to the assumption in top position once all the
previous :token:`i_item` have been performed.
@@ -1608,6 +1635,9 @@ Notations can be used to name tactics, for example::
lets one write just ``/myop`` in the intro pattern. Note the scope
annotation: views are interpreted opening the ``ssripat`` scope.
+Intro patterns
+``````````````
+
|SSR| supports the following :token:`i_pattern`\s:
:token:`ident`
@@ -1615,6 +1645,13 @@ annotation: views are interpreted opening the ``ssripat`` scope.
a new constant, fact, or defined constant :token:`ident`, respectively.
Note that defined constants cannot be introduced when δ-expansion is
required to expose the top variable or assumption.
+ A :token:`clear_switch` (even an empty one) immediately preceding an
+ :token:`ident` is complemented with that :token:`ident` if and only if
+ the identifier is a simple proof context entry [#10]_.
+ As a consequence by prefixing the
+ :token:`ident` with ``{}`` one can *replace* a context entry.
+ This behavior can be avoided by separating the :token:`clear_switch`
+ from the :token:`ident` with the ``-`` intro pattern.
``>``
pops every variable occurring in the rest of the stack.
Type class instances are popped even if they don't occur
@@ -1708,6 +1745,9 @@ annotation: views are interpreted opening the ``ssripat`` scope.
Note that |SSR| does not support the syntax ``(ipat, …, ipat)`` for
destructing intro-patterns.
+Clear switch
+````````````
+
Clears are deferred until the end of the intro pattern.
.. example::
@@ -1730,6 +1770,9 @@ is performed behind the scenes.
Facts mentioned in a clear switch must be valid names in the proof
context (excluding the section context).
+Branching and destructuring
+```````````````````````````
+
The rules for interpreting branching and destructing :token:`i_pattern` are
motivated by the fact that it would be pointless to have a branching
pattern if tactic is a ``move``, and in most of the remaining cases
@@ -1754,6 +1797,9 @@ interpretation, e.g.:
are all equivalent.
+Block introduction
+``````````````````
+
|SSR| supports the following :token:`i_block`\s:
:n:`[^ @ident ]`
@@ -3030,13 +3076,22 @@ operation should be performed:
pattern. In its simplest form, it is a regular term. If no explicit
redex switch is present the rewrite pattern to be matched is inferred
from the :token:`r_item`.
-+ This optional term, or the :token:`r_item`, may be preceded by an occurrence
- switch (see section :ref:`selectors_ssr`) or a clear item
- (see section :ref:`discharge_ssr`),
- these two possibilities being exclusive. An occurrence switch selects
++ This optional term, or the :token:`r_item`, may be preceded by an
+ :token:`occ_switch` (see section :ref:`selectors_ssr`) or a
+ :token:`clear_switch` (see section :ref:`discharge_ssr`),
+ these two possibilities being exclusive.
+
+ An occurrence switch selects
the occurrences of the rewrite pattern which should be affected by the
rewrite operation.
+ A clear switch, even an empty one, is performed *after* the
+ :token:`r_item` is actually processed and is complemented with the name of
+ the rewrite rule if an only if it is a simple proof context entry [#10]_.
+ As a consequence one can
+ write ``rewrite {}H`` to rewrite with ``H`` and dispose ``H`` immediately
+ afterwards.
+ This behavior can be avoided by putting parentheses around the rewrite rule.
An :token:`r_item` can be:
@@ -3291,10 +3346,6 @@ the rewrite tactic. The effect of the tactic on the initial goal is to
rewrite this lemma at the second occurrence of the first matching
``x + y + 0`` of the explicit rewrite redex ``_ + y + 0``.
-An empty occurrence switch ``{}`` is not interpreted as a valid occurrence
-switch. It has the effect of clearing the :token:`r_item` (when it is the name
-of a context entry).
-
Occurrence selection and repetition
```````````````````````````````````
@@ -5520,3 +5571,5 @@ Settings
in the metatheory
.. [#9] The current state of the proof shall be displayed by the Show
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 554bfefa0a..081fef07b9 100644
--- a/doc/sphinx/proof-engine/tactics.rst
+++ b/doc/sphinx/proof-engine/tactics.rst
@@ -33,10 +33,13 @@ extends the folklore notion of tactical) to combine those atomic
tactics. This chapter is devoted to atomic tactics. The tactic
language will be described in Chapter :ref:`ltac`.
+Common elements of tactics
+--------------------------
+
.. _invocation-of-tactics:
Invocation of tactics
--------------------------
+~~~~~~~~~~~~~~~~~~~~~
A tactic is applied as an ordinary command. It may be preceded by a
goal selector (see Section :ref:`ltac-semantics`). If no selector is
@@ -44,9 +47,9 @@ specified, the default selector is used.
.. _tactic_invocation_grammar:
- .. productionlist:: `sentence`
- tactic_invocation : toplevel_selector : tactic.
- : |tactic .
+ .. productionlist:: sentence
+ tactic_invocation : `toplevel_selector` : `tactic`.
+ : `tactic`.
.. opt:: Default Goal Selector "@toplevel_selector"
:name: Default Goal Selector
@@ -71,29 +74,31 @@ specified, the default selector is used.
Bindings list
~~~~~~~~~~~~~~~~~~~
-Tactics that take a term as argument may also support a bindings list,
-so as to instantiate some parameters of the term by name or position.
-The general form of a term equipped with a bindings list is ``term with
-bindings_list`` where ``bindings_list`` may be of two different forms:
+Tactics that take a term as an argument may also support a bindings list
+to instantiate some parameters of the term by name or position.
+The general form of a term with a bindings list is
+:n:`@term with @bindings_list` where :token:`bindings_list` can take two different forms:
.. _bindings_list_grammar:
- .. productionlist:: `bindings_list`
- bindings_list : (ref := `term`) ... (ref := `term`)
+ .. productionlist:: bindings_list
+ ref : `ident`
+ : `num`
+ bindings_list : (`ref` := `term`) ... (`ref` := `term`)
: `term` ... `term`
-+ In a bindings list of the form :n:`{* (ref:= term)}`, :n:`ref` is either an
++ In a bindings list of the form :n:`{+ (@ref:= @term)}`, :n:`@ref` is either an
:n:`@ident` or a :n:`@num`. The references are determined according to the type of
- ``term``. If :n:`ref` is an identifier, this identifier has to be bound in the
- type of ``term`` and the binding provides the tactic with an instance for the
- parameter of this name. If :n:`ref` is some number ``n``, this number denotes
- the ``n``-th non dependent premise of the ``term``, as determined by the type
- of ``term``.
+ :n:`@term`. If :n:`@ref` is an identifier, this identifier has to be bound in the
+ type of :n:`@term` and the binding provides the tactic with an instance for the
+ parameter of this name. If :n:`@ref` is a number ``n``, it refers to
+ the ``n``-th non dependent premise of the :n:`@term`, as determined by the type
+ of :n:`@term`.
.. exn:: No such binder.
:undocumented:
-+ A bindings list can also be a simple list of terms :n:`{* term}`.
++ A bindings list can also be a simple list of terms :n:`{* @term}`.
In that case the references to which these terms correspond are
determined by the tactic. In case of :tacn:`induction`, :tacn:`destruct`, :tacn:`elim`
and :tacn:`case`, the terms have to
@@ -105,6 +110,350 @@ bindings_list`` where ``bindings_list`` may be of two different forms:
.. exn:: Not the right number of missing arguments.
:undocumented:
+.. _intropatterns:
+
+Intro patterns
+~~~~~~~~~~~~~~
+
+Intro patterns let you specify the name to assign to variables and hypotheses
+introduced by tactics. They also let you split an introduced hypothesis into
+multiple hypotheses or subgoals. Common tactics that accept intro patterns
+include :tacn:`assert`, :tacn:`intros` and :tacn:`destruct`.
+
+.. productionlist:: coq
+ intropattern_list : `intropattern` ... `intropattern`
+ : `empty`
+ empty :
+ intropattern : *
+ : **
+ : `simple_intropattern`
+ simple_intropattern : `simple_intropattern_closed` [ % `term` ... % `term` ]
+ simple_intropattern_closed : `naming_intropattern`
+ : _
+ : `or_and_intropattern`
+ : `equality_intropattern`
+ naming_intropattern : `ident`
+ : ?
+ : ?`ident`
+ or_and_intropattern : [ `intropattern_list` | ... | `intropattern_list` ]
+ : ( `simple_intropattern` , ... , `simple_intropattern` )
+ : ( `simple_intropattern` & ... & `simple_intropattern` )
+ equality_intropattern : ->
+ : <-
+ : [= `intropattern_list` ]
+ or_and_intropattern_loc : `or_and_intropattern`
+ : `ident`
+
+Note that the intro pattern syntax varies between tactics.
+Most tactics use :n:`@simple_intropattern` in the grammar.
+:tacn:`destruct`, :tacn:`edestruct`, :tacn:`induction`,
+:tacn:`einduction`, :tacn:`case`, :tacn:`ecase` and the various
+:tacn:`inversion` tactics use :n:`@or_and_intropattern_loc`, while
+:tacn:`intros` and :tacn:`eintros` use :n:`@intropattern_list`.
+The :n:`eqn:` construct in various tactics uses :n:`@naming_intropattern`.
+
+**Naming patterns**
+
+Use these elementary patterns to specify a name:
+
+* :n:`@ident` - use the specified 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
+
+**Splitting patterns**
+
+The most common splitting patterns are:
+
+* split a hypothesis in the form :n:`A /\ B` into two
+ hypotheses :g:`H1: A` and :g:`H2: B` using the pattern :g:`(H1 & H2)` or
+ :g:`(H1, H2)` or :g:`[H1 H2]`.
+ :ref:`Example <intropattern_conj_ex>`. This also works on :n:`A <-> B`, which
+ is just a notation representing :n:`(A -> B) /\ (B -> A)`.
+* split a hypothesis in the form :g:`A \/ B` into two
+ subgoals using the pattern :g:`[H1|H2]`. The first subgoal will have the hypothesis
+ :g:`H1: A` and the second subgoal will have the hypothesis :g:`H2: B`.
+ :ref:`Example <intropattern_disj_ex>`
+* split a hypothesis in either of the forms :g:`A /\ B` or :g:`A \/ B` using the pattern :g:`[]`.
+
+Patterns can be nested: :n:`[[Ha|Hb] H]` can be used to split :n:`(A \/ B) /\ C`.
+
+Note that there is no equivalent to intro patterns for goals. For a goal :g:`A /\ B`,
+use the :tacn:`split` tactic to replace the current goal with subgoals :g:`A` and :g:`B`.
+For a goal :g:`A \/ B`, use :tacn:`left` to replace the current goal with :g:`A`, or
+:tacn:`right` to replace the current goal with :g:`B`.
+
+* :n:`( {+, @simple_intropattern}` ) - matches
+ a product over an inductive type with a
+ :ref:`single constructor <intropattern_cons_note>`.
+ If the number of patterns
+ equals the number of constructor arguments, then it applies the patterns only to
+ the arguments, and
+ :n:`( {+, @simple_intropattern} )` is equivalent to :n:`[{+ @simple_intropattern}]`.
+ If the number of patterns equals the number of constructor arguments plus the number
+ of :n:`let-ins`, the patterns are applied to the arguments and :n:`let-in` variables.
+
+* :n:`( {+& @simple_intropattern} )` - matches a right-hand nested term that consists
+ of one or more nested binary inductive types such as :g:`a1 OP1 a2 OP2 ...`
+ (where the :g:`OPn` are right-associative).
+ (If the :g:`OPn` are left-associative, additional parentheses will be needed to make the
+ term right-hand nested, such as :g:`a1 OP1 (a2 OP2 ...)`.)
+ The splitting pattern can have more than 2 names, for example :g:`(H1 & H2 & H3)`
+ matches :g:`A /\ B /\ C`.
+ The inductive types must have a
+ :ref:`single constructor with two parameters <intropattern_cons_note>`.
+ :ref:`Example <intropattern_ampersand_ex>`
+
+* :n:`[ {+| @intropattern_list} ]` - splits an inductive type that has
+ :ref:`multiple constructors <intropattern_cons_note>`
+ such as :n:`A \/ B`
+ into multiple subgoals. The number of :token:`intropattern_list` must be the same as the number of
+ constructors for the matched part.
+* :n:`[ {+ @intropattern} ]` - splits an inductive type that has a
+ :ref:`single constructor with multiple parameters <intropattern_cons_note>`
+ such as :n:`A /\ B` into multiple hypotheses. Use :n:`[H1 [H2 H3]]` to match :g:`A /\ B /\ C`.
+* :n:`[]` - splits an inductive type: If the inductive
+ type has multiple constructors, such as :n:`A \/ B`,
+ create one subgoal for each constructor. If the inductive type has a single constructor with
+ multiple parameters, such as :n:`A /\ B`, split it into multiple hypotheses.
+
+**Equality patterns**
+
+These patterns can be used when the hypothesis is an equality:
+
+* :n:`->` - replaces the right-hand side of the hypothesis with the left-hand
+ side of the hypothesis in the conclusion of the goal; the hypothesis is
+ cleared; if the left-hand side of the hypothesis is a variable, it is
+ substituted everywhere in the context and the variable is removed.
+ :ref:`Example <intropattern_rarrow_ex>`
+* :n:`<-` - similar to :n:`->`, but replaces the left-hand side of the hypothesis
+ with the right-hand side of the hypothesis.
+* :n:`[= {*, @intropattern} ]` - If the product is over an equality type,
+ applies either :tacn:`injection` or :tacn:`discriminate`.
+ If :tacn:`injection` is applicable, the intropattern
+ is used on the hypotheses generated by :tacn:`injection`. If the
+ number of patterns is smaller than the number of hypotheses generated, the
+ pattern :n:`?` is used to complete the list.
+ :ref:`Example <intropattern_inj_discr_ex>`
+
+**Other patterns**
+
+* :n:`*` - introduces one or more quantified variables from the result
+ until there are no more quantified variables.
+ :ref:`Example <intropattern_star_ex>`
+
+* :n:`**` - introduces one or more quantified variables or hypotheses from the result until there are
+ no more quantified variables or implications (:g:`->`). :g:`intros **` is equivalent
+ to :g:`intros`.
+ :ref:`Example <intropattern_2stars_ex>`
+
+* :n:`@simple_intropattern_closed {* % @term}` - first applies each of the terms
+ with the :tacn:`apply ... in` tactic on the hypothesis to be introduced, then it uses
+ :n:`@simple_intropattern_closed`.
+ :ref:`Example <intropattern_injection_ex>`
+
+.. flag:: Bracketing Last Introduction Pattern
+
+ 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
+ additional names to match the number of arguments.
+ Unsetting the option will put the additional hypotheses in the goal instead, behavior that is more
+ similar to |SSR|'s intro patterns.
+
+ .. deprecated:: 8.10
+
+.. _intropattern_cons_note:
+
+.. note::
+
+ :n:`A \/ B` and :n:`A /\ B` use infix notation to refer to the inductive
+ types :n:`or` and :n:`and`.
+ :n:`or` has multiple constructors (:n:`or_introl` and :n:`or_intror`),
+ while :n:`and` has a single constructor (:n:`conj`) with multiple parameters
+ (:n:`A` and :n:`B`).
+ These are defined in theories/Init/Logic.v. The "where" clauses define the
+ infix notation for "or" and "and".
+
+ .. coqdoc::
+
+ Inductive or (A B:Prop) : Prop :=
+ | or_introl : A -> A \/ B
+ | or_intror : B -> A \/ B
+ where "A \/ B" := (or A B) : type_scope.
+
+ Inductive and (A B:Prop) : Prop :=
+ conj : A -> B -> A /\ B
+ where "A /\ B" := (and A B) : type_scope.
+
+.. note::
+
+ :n:`intros {+ p}` is not always equivalent to :n:`intros p; ... ; intros p`
+ if some of the :n:`p` are :g:`_`. In the first form, all erasures are done
+ at once, while they're done sequentially for each tactic in the second form.
+ If the second matched term depends on the first matched term and the pattern
+ for both is :g:`_` (i.e., both will be erased), the first :n:`intros` in the second
+ form will fail because the second matched term still has the dependency on the first.
+
+Examples:
+
+.. _intropattern_conj_ex:
+
+ .. example:: intro pattern for /\\
+
+ .. coqtop:: reset none
+
+ Goal forall (A: Prop) (B: Prop), (A /\ B) -> True.
+
+ .. coqtop:: out
+
+ intros.
+
+ .. coqtop:: all
+
+ destruct H as (HA & HB).
+
+.. _intropattern_disj_ex:
+
+ .. example:: intro pattern for \\/
+
+ .. coqtop:: reset none
+
+ Goal forall (A: Prop) (B: Prop), (A \/ B) -> True.
+
+ .. coqtop:: out
+
+ intros.
+
+ .. coqtop:: all
+
+ destruct H as [HA|HB]. all: swap 1 2.
+
+.. _intropattern_rarrow_ex:
+
+ .. example:: -> intro pattern
+
+ .. coqtop:: reset none
+
+ Goal forall (x:nat) (y:nat) (z:nat), (x = y) -> (y = z) -> (x = z).
+
+ .. coqtop:: out
+
+ intros * H.
+
+ .. coqtop:: all
+
+ intros ->.
+
+.. _intropattern_inj_discr_ex:
+
+ .. example:: [=] intro pattern
+
+ The first :n:`intros [=]` uses :tacn:`injection` to strip :n:`(S ...)` from
+ both sides of the matched equality. The second uses :tacn:`discriminate` on
+ the contradiction :n:`1 = 2` (internally represented as :n:`(S O) = (S (S O))`)
+ to complete the goal.
+
+ .. coqtop:: reset none
+
+ Goal forall (n m:nat), (S n) = (S m) -> (S O)=(S (S O)) -> False.
+
+ .. coqtop:: out
+
+ intros *.
+
+ .. coqtop:: all
+
+ intros [= H].
+
+ .. coqtop:: all
+
+ intros [=].
+
+.. _intropattern_ampersand_ex:
+
+ .. example:: (A & B & ...) intro pattern
+
+ .. coqtop:: reset none
+
+ Variables (A : Prop) (B: nat -> Prop) (C: Prop).
+
+ .. coqtop:: out
+
+ Goal A /\ (exists x:nat, B x /\ C) -> True.
+
+ .. coqtop:: all
+
+ intros (a & x & b & c).
+
+.. _intropattern_star_ex:
+
+ .. example:: * intro pattern
+
+ .. coqtop:: reset out
+
+ Goal forall (A: Prop) (B: Prop), A -> B.
+
+ .. coqtop:: all
+
+ intros *.
+
+.. _intropattern_2stars_ex:
+
+ .. example:: ** pattern ("intros \**" is equivalent to "intros")
+
+ .. coqtop:: reset out
+
+ Goal forall (A: Prop) (B: Prop), A -> B.
+
+ .. coqtop:: all
+
+ intros **.
+
+ .. example:: compound intro pattern
+
+ .. coqtop:: reset out
+
+ Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C.
+
+ .. coqtop:: all
+
+ intros * [a | (_,c)] f.
+ all: swap 1 2.
+
+.. _intropattern_injection_ex:
+
+ .. example:: combined intro pattern using [=] -> and %
+
+ .. coqtop:: reset none
+
+ Require Import Coq.Lists.List.
+ Section IntroPatterns.
+ Variables (A : Type) (xs ys : list A).
+
+ .. coqtop:: out
+
+ Example ThreeIntroPatternsCombined :
+ S (length ys) = 1 -> xs ++ ys = xs.
+
+ .. coqtop:: all
+
+ intros [=->%length_zero_iff_nil].
+
+ * `intros` would add :g:`H : S (length ys) = 1`
+ * `intros [=]` would additionally apply :tacn:`injection` to :g:`H` to yield :g:`H0 : length ys = 0`
+ * `intros [=->%length_zero_iff_nil]` applies the theorem, making H the equality :g:`l=nil`,
+ which is then applied as for :g:`->`.
+
+ .. coqdoc::
+
+ Theorem length_zero_iff_nil (l : list A):
+ length l = 0 <-> l=nil.
+
+ The example is based on `Tej Chajed's coq-tricks <https://github.com/tchajed/coq-tricks/blob/8e6efe4971ed828ac8bdb5512c1f615d7d62691e/src/IntroPatterns.v>`_
+
.. _occurrencessets:
Occurrence sets and occurrence clauses
@@ -113,11 +462,11 @@ Occurrence sets and occurrence clauses
An occurrence clause is a modifier to some tactics that obeys the
following syntax:
- .. productionlist:: `sentence`
+ .. productionlist:: sentence
occurrence_clause : in `goal_occurrences`
- goal_occurrences : [`ident` [`at_occurrences`], ... , ident [`at_occurrences`] [|- [* [`at_occurrences`]]]]
- :| * |- [* [`at_occurrences`]]
- :| *
+ goal_occurrences : [`ident` [`at_occurrences`], ... , `ident` [`at_occurrences`] [|- [* [`at_occurrences`]]]]
+ : * |- [* [`at_occurrences`]]
+ : *
at_occurrences : at `occurrences`
occurrences : [-] `num` ... `num`
@@ -508,10 +857,10 @@ Applying theorems
This works as :tacn:`apply ... in` but turns unresolved bindings into
existential variables, if any, instead of failing.
- .. tacv:: apply {+, @term {? with @bindings_list } } in @ident as @intro_pattern
+ .. tacv:: apply {+, @term {? with @bindings_list } } in @ident as @simple_intropattern
:name: apply ... in ... as
- This works as :tacn:`apply ... in` then applies the :token:`intro_pattern`
+ This works as :tacn:`apply ... in` then applies the :token:`simple_intropattern`
to the hypothesis :token:`ident`.
.. tacv:: simple apply @term in @ident
@@ -525,8 +874,8 @@ Applying theorems
Tactic :n:`simple apply @term in @ident` does not
either traverse tuples as :n:`apply @term in @ident` does.
- .. tacv:: {? simple} apply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
- {? simple} eapply {+, @term {? with @bindings_list}} in @ident {? as @intro_pattern}
+ .. tacv:: {? simple} apply {+, @term {? with @bindings_list}} in @ident {? as @simple_intropattern}
+ {? simple} eapply {+, @term {? with @bindings_list}} in @ident {? as @simple_intropattern}
This summarizes the different syntactic variants of :n:`apply @term in @ident`
and :n:`eapply @term in @ident`.
@@ -726,149 +1075,17 @@ Managing the local context
.. exn:: No such hypothesis: @ident.
:undocumented:
-.. tacn:: intros @intro_pattern_list
+.. tacn:: intros @intropattern_list
:name: intros ...
- This extension of the tactic :n:`intros` allows to apply tactics on the fly
- on the variables or hypotheses which have been introduced. An
- *introduction pattern list* :n:`@intro_pattern_list` is a list of
- introduction patterns possibly containing the filling introduction
- patterns `*` and `**`. An *introduction pattern* is either:
-
- + a *naming introduction pattern*, i.e. either one of:
-
- + the pattern :n:`?`
-
- + the pattern :n:`?ident`
-
- + an identifier
-
- + an *action introduction pattern* which itself classifies into:
-
- + a *disjunctive/conjunctive introduction pattern*, i.e. either one of
-
- + a disjunction of lists of patterns
- :n:`[@intro_pattern_list | ... | @intro_pattern_list]`
-
- + a conjunction of patterns: :n:`({+, p})`
-
- + a list of patterns
- :n:`({+& p})`
- for sequence of right-associative binary constructs
-
- + an *equality introduction pattern*, i.e. either one of:
+ Introduces one or more variables or hypotheses from the goal by matching the
+ intro patterns. See the description in :ref:`intropatterns`.
- + a pattern for decomposing an equality: :n:`[= {+ p}]`
- + the rewriting orientations: :n:`->` or :n:`<-`
+.. tacn:: eintros @intropattern_list
+ :name: eintros
- + the on-the-fly application of lemmas: :n:`p{+ %term}` where :n:`p`
- itself is not a pattern for on-the-fly application of lemmas (note:
- syntax is in experimental stage)
-
- + the wildcard: :n:`_`
-
-
- Assuming a goal of type :g:`Q → P` (non-dependent product), or of type
- :g:`forall x:T, P` (dependent product), the behavior of
- :n:`intros p` is defined inductively over the structure of the introduction
- pattern :n:`p`:
-
- Introduction on :n:`?` performs the introduction, and lets Coq choose a fresh
- name for the variable;
-
- Introduction on :n:`?@ident` performs the introduction, and lets Coq choose a
- fresh name for the variable based on :n:`@ident`;
-
- Introduction on :n:`@ident` behaves as described in :tacn:`intro`
-
- Introduction over a disjunction of list of patterns
- :n:`[@intro_pattern_list | ... | @intro_pattern_list ]` expects the product
- to be over an inductive type whose number of constructors is `n` (or more
- generally over a type of conclusion an inductive type built from `n`
- constructors, e.g. :g:`C -> A\/B` with `n=2` since :g:`A\/B` has `2`
- constructors): it destructs the introduced hypothesis as :n:`destruct` (see
- :tacn:`destruct`) would and applies on each generated subgoal the
- corresponding tactic;
-
- The introduction patterns in :n:`@intro_pattern_list` are expected to consume
- no more than the number of arguments of the `i`-th constructor. If it
- consumes less, then Coq completes the pattern so that all the arguments of
- the constructors of the inductive type are introduced (for instance, the
- list of patterns :n:`[ | ] H` applied on goal :g:`forall x:nat, x=0 -> 0=x`
- behaves the same as the list of patterns :n:`[ | ? ] H`);
-
- Introduction over a conjunction of patterns :n:`({+, p})` expects
- the goal to be a product over an inductive type :g:`I` with a single
- constructor that itself has at least `n` arguments: It performs a case
- analysis over the hypothesis, as :n:`destruct` would, and applies the
- patterns :n:`{+ p}` to the arguments of the constructor of :g:`I` (observe
- that :n:`({+ p})` is an alternative notation for :n:`[{+ p}]`);
-
- Introduction via :n:`({+& p})` is a shortcut for introduction via
- :n:`(p,( ... ,( ..., p ) ... ))`; it expects the hypothesis to be a sequence of
- right-associative binary inductive constructors such as :g:`conj` or
- :g:`ex_intro`; for instance, a hypothesis with type
- :g:`A /\(exists x, B /\ C /\ D)` can be introduced via pattern
- :n:`(a & x & b & c & d)`;
-
- If the product is over an equality type, then a pattern of the form
- :n:`[= {+ p}]` applies either :tacn:`injection` or :tacn:`discriminate`
- instead of :tacn:`destruct`; if :tacn:`injection` is applicable, the patterns
- :n:`{+, p}` are used on the hypotheses generated by :tacn:`injection`; if the
- number of patterns is smaller than the number of hypotheses generated, the
- pattern :n:`?` is used to complete the list.
-
- Introduction over ``->`` (respectively over ``<-``)
- expects the hypothesis to be an equality and the right-hand-side
- (respectively the left-hand-side) is replaced by the left-hand-side
- (respectively the right-hand-side) in the conclusion of the goal;
- the hypothesis itself is erased; if the term to substitute is a variable, it
- is substituted also in the context of goal and the variable is removed too.
-
- Introduction over a pattern :n:`p{+ %term}` first applies :n:`{+ term}`
- on the hypothesis to be introduced (as in :n:`apply {+, term}`) prior to the
- application of the introduction pattern :n:`p`;
-
- Introduction on the wildcard depends on whether the product is dependent or not:
- in the non-dependent case, it erases the corresponding hypothesis (i.e. it
- behaves as an :tacn:`intro` followed by a :tacn:`clear`) while in the
- dependent case, it succeeds and erases the variable only if the wildcard is part
- of a more complex list of introduction patterns that also erases the hypotheses
- depending on this variable;
-
- Introduction over :n:`*` introduces all forthcoming quantified variables
- appearing in a row; introduction over :n:`**` introduces all forthcoming
- quantified variables or hypotheses until the goal is not any more a
- quantification or an implication.
-
- .. example::
-
- .. coqtop:: reset all
-
- Goal forall A B C:Prop, A \/ B /\ C -> (A -> C) -> C.
- intros * [a | (_,c)] f.
-
-.. note::
-
- :n:`intros {+ p}` is not equivalent to :n:`intros p; ... ; intros p`
- for the following reason: If one of the :n:`p` is a wildcard pattern, it
- might succeed in the first case because the further hypotheses it
- depends on are eventually erased too while it might fail in the second
- case because of dependencies in hypotheses which are not yet
- introduced (and a fortiori not yet erased).
-
-.. note::
-
- In :n:`intros @intro_pattern_list`, if the last introduction pattern
- is a disjunctive or conjunctive pattern
- :n:`[{+| @intro_pattern_list}]`, the completion of :n:`@intro_pattern_list`
- so that all the arguments of the i-th constructors of the corresponding
- inductive type are introduced can be controlled with the following option:
-
- .. flag:: Bracketing Last Introduction Pattern
-
- Force completion, if needed, when the last introduction pattern is a
- disjunctive or conjunctive pattern (on by default).
+ Works just like :tacn:`intros ...` except that it creates existential variables
+ for any unresolved variables rather than failing.
.. tacn:: clear @ident
:name: clear
@@ -1057,19 +1274,19 @@ Managing the local context
used as a synonym of :tacn:`epose`, i.e. when the :token:`term` does
not occur in the goal.
-.. tacn:: remember @term as @ident__1 {? eqn:@ident__2 }
+.. tacn:: remember @term as @ident__1 {? eqn:@naming_intropattern }
:name: remember
- This behaves as :n:`set (@ident__1 := @term) in *`, using a logical
+ This behaves as :n:`set (@ident := @term) in *`, using a logical
(Leibniz’s) equality instead of a local definition.
- If :n:`@ident__2` is provided, it will be the name of the new equation.
+ Use :n:`@naming_intropattern` to name or split up the new equation.
- .. tacv:: remember @term as @ident__1 {? eqn:@ident__2 } in @goal_occurrences
+ .. tacv:: remember @term as @ident__1 {? eqn:@naming_intropattern } in @goal_occurrences
This is a more general form of :tacn:`remember` that remembers the
occurrences of :token:`term` specified by an occurrence set.
- .. tacv:: eremember @term as @ident__1 {? eqn:@ident__2 } {? in @goal_occurrences }
+ .. tacv:: eremember @term as @ident__1 {? eqn:@naming_intropattern } {? in @goal_occurrences }
:name: eremember
While the different variants of :tacn:`remember` expect that no
@@ -1163,16 +1380,16 @@ Controlling the proof flow
:name: Proof is not complete. (assert)
:undocumented:
- .. tacv:: assert @type as @intro_pattern
+ .. tacv:: assert @type as @simple_intropattern
- If :n:`intro_pattern` is a naming introduction pattern (see :tacn:`intro`),
+ If :n:`simple_intropattern` is an intro pattern (see :ref:`intropatterns`),
the hypothesis is named after this introduction pattern (in particular, if
- :n:`intro_pattern` is :n:`@ident`, the tactic behaves like
- :n:`assert (@ident : @type)`). If :n:`intro_pattern` is an action
+ :n:`simple_intropattern` is :n:`@ident`, the tactic behaves like
+ :n:`assert (@ident : @type)`). If :n:`simple_intropattern` is an action
introduction pattern, the tactic behaves like :n:`assert @type` followed by
the action done by this introduction pattern.
- .. tacv:: assert @type as @intro_pattern by @tactic
+ .. tacv:: assert @type as @simple_intropattern by @tactic
This combines the two previous variants of :tacn:`assert`.
@@ -1186,7 +1403,7 @@ Controlling the proof flow
.. exn:: Variable @ident is already declared.
:undocumented:
-.. tacv:: eassert @type as @intro_pattern by @tactic
+.. tacv:: eassert @type as @simple_intropattern by @tactic
:name: eassert
While the different variants of :tacn:`assert` expect that no existential
@@ -1194,16 +1411,16 @@ Controlling the proof flow
This allows not to specify the asserted statement completeley before starting
to prove it.
-.. tacv:: pose proof @term {? as @intro_pattern}
+.. tacv:: pose proof @term {? as @simple_intropattern}
:name: pose proof
- This tactic behaves like :n:`assert @type {? as @intro_pattern} by exact @term`
+ This tactic behaves like :n:`assert @type {? as @simple_intropattern} by exact @term`
where :token:`type` is the type of :token:`term`. In particular,
:n:`pose proof @term as @ident` behaves as :n:`assert (@ident := @term)`
- and :n:`pose proof @term as @intro_pattern` is the same as applying the
- :token:`intro_pattern` to :token:`term`.
+ and :n:`pose proof @term as @simple_intropattern` is the same as applying the
+ :token:`simple_intropattern` to :token:`term`.
-.. tacv:: epose proof @term {? as @intro_pattern}
+.. tacv:: epose proof @term {? as @simple_intropattern}
:name: epose proof
While :tacn:`pose proof` expects that no existential variables are generated by
@@ -1221,20 +1438,20 @@ Controlling the proof flow
This behaves like :n:`enough (@ident : @type)` with the name :token:`ident` of
the hypothesis generated by Coq.
-.. tacv:: enough @type as @intro_pattern
+.. tacv:: enough @type as @simple_intropattern
- This behaves like :n:`enough @type` using :token:`intro_pattern` to name or
+ This behaves like :n:`enough @type` using :token:`simple_intropattern` to name or
destruct the new hypothesis.
.. tacv:: enough (@ident : @type) by @tactic
- enough @type {? as @intro_pattern } by @tactic
+ enough @type {? as @simple_intropattern } by @tactic
This behaves as above but with :token:`tactic` expected to solve the initial goal
after the extra assumption :token:`type` is added and possibly destructed. If the
- :n:`as @intro_pattern` clause generates more than one subgoal, :token:`tactic` is
+ :n:`as @simple_intropattern` clause generates more than one subgoal, :token:`tactic` is
applied to all of them.
-.. tacv:: eenough @type {? as @intro_pattern } {? by @tactic }
+.. tacv:: eenough @type {? as @simple_intropattern } {? by @tactic }
eenough (@ident : @type) {? by @tactic }
:name: eenough; _
@@ -1250,8 +1467,8 @@ Controlling the proof flow
subgoals: :g:`U -> T` and :g:`U`. The subgoal :g:`U -> T` comes first in the
list of remaining subgoal to prove.
-.. tacv:: specialize (@ident {* @term}) {? as @intro_pattern}
- specialize @ident with @bindings_list {? as @intro_pattern}
+.. tacv:: specialize (@ident {* @term}) {? as @simple_intropattern}
+ specialize @ident with @bindings_list {? as @simple_intropattern}
:name: specialize; _
This tactic works on local hypothesis :n:`@ident`. The
@@ -1264,7 +1481,7 @@ Controlling the proof flow
uninstantiated arguments are inferred by unification if possible or left
quantified in the hypothesis otherwise. With the :n:`as` clause, the local
hypothesis :n:`@ident` is left unchanged and instead, the modified hypothesis
- is introduced as specified by the :token:`intro_pattern`. The name :n:`@ident`
+ is introduced as specified by the :token:`simple_intropattern`. The name :n:`@ident`
can also refer to a global lemma or hypothesis. In this case, for
compatibility reasons, the behavior of :tacn:`specialize` is close to that of
:tacn:`generalize`: the instantiated statement becomes an additional premise of
@@ -1477,11 +1694,11 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
This is a shortcut for :n:`destruct @term; ...; destruct @term`.
- .. tacv:: destruct @term as @disj_conj_intro_pattern
+ .. tacv:: destruct @term as @or_and_intropattern_loc
This behaves as :n:`destruct @term` but uses the names
- in :token:`disj_conj_intro_pattern` to name the variables introduced in the
- context. The :token:`disj_conj_intro_pattern` must have the
+ in :token:`or_and_intropattern_loc` to name the variables introduced in the
+ context. The :token:`or_and_intropattern_loc` must have the
form :n:`[p11 ... p1n | ... | pm1 ... pmn ]` with ``m`` being the
number of constructors of the type of :token:`term`. Each variable
introduced by :tacn:`destruct` in the context of the ``i``-th goal
@@ -1491,13 +1708,13 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
pattern (see :tacn:`intros`). This provides a concise notation for
chaining destruction of a hypothesis.
- .. tacv:: destruct @term eqn:@naming_intro_pattern
+ .. tacv:: destruct @term eqn:@naming_intropattern
:name: destruct ... eqn:
This behaves as :n:`destruct @term` but adds an equation
between :token:`term` and the value that it takes in each of the
possible cases. The name of the equation is specified
- by :token:`naming_intro_pattern` (see :tacn:`intros`),
+ by :token:`naming_intropattern` (see :tacn:`intros`),
in particular ``?`` can be used to let Coq generate a fresh name.
.. tacv:: destruct @term with @bindings_list
@@ -1525,8 +1742,8 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
clause is an occurrence clause whose syntax and behavior is described
in :ref:`occurrences sets <occurrencessets>`.
- .. tacv:: destruct @term {? with @bindings_list } {? as @disj_conj_intro_pattern } {? eqn:@naming_intro_pattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
- edestruct @term {? with @bindings_list } {? as @disj_conj_intro_pattern } {? eqn:@naming_intro_pattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
+ .. tacv:: destruct @term {? with @bindings_list } {? as @or_and_intropattern_loc } {? eqn:@naming_intropattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
+ edestruct @term {? with @bindings_list } {? as @or_and_intropattern_loc } {? eqn:@naming_intropattern } {? using @term {? with @bindings_list } } {? in @goal_occurrences }
These are the general forms of :tacn:`destruct` and :tacn:`edestruct`.
They combine the effects of the ``with``, ``as``, ``eqn:``, ``using``,
@@ -1622,11 +1839,11 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
Use in this case the variant :tacn:`elim ... with` below.
-.. tacv:: induction @term as @disj_conj_intro_pattern
+.. tacv:: induction @term as @or_and_intropattern_loc
This behaves as :tacn:`induction` but uses the names in
- :n:`@disj_conj_intro_pattern` to name the variables introduced in the
- context. The :n:`@disj_conj_intro_pattern` must typically be of the form
+ :n:`@or_and_intropattern_loc` to name the variables introduced in the
+ context. The :n:`@or_and_intropattern_loc` must typically be of the form
:n:`[ p` :sub:`11` :n:`... p` :sub:`1n` :n:`| ... | p`:sub:`m1` :n:`... p`:sub:`mn` :n:`]`
with :n:`m` being the number of constructors of the type of :n:`@term`. Each
variable introduced by induction in the context of the i-th goal gets its
@@ -1686,8 +1903,8 @@ analysis on inductive or co-inductive objects (see :ref:`inductive-definitions`)
induction y in x |- *.
Show 2.
-.. tacv:: induction @term with @bindings_list as @disj_conj_intro_pattern using @term with @bindings_list in @goal_occurrences
- einduction @term with @bindings_list as @disj_conj_intro_pattern using @term with @bindings_list in @goal_occurrences
+.. tacv:: induction @term with @bindings_list as @or_and_intropattern_loc using @term with @bindings_list in @goal_occurrences
+ einduction @term with @bindings_list as @or_and_intropattern_loc using @term with @bindings_list in @goal_occurrences
These are the most general forms of :tacn:`induction` and :tacn:`einduction`. It combines the
effects of the with, as, using, and in clauses.
@@ -1898,7 +2115,7 @@ and an explanation of the underlying technique.
.. exn:: Not the right number of induction arguments.
:undocumented:
-.. tacv:: functional induction (@qualid {+ @term}) as @disj_conj_intro_pattern using @term with @bindings_list
+.. tacv:: functional induction (@qualid {+ @term}) as @simple_intropattern using @term with @bindings_list
Similarly to :tacn:`induction` and :tacn:`elim`, this allows giving
explicitly the name of the introduced variables, the induction principle, and
@@ -2053,18 +2270,18 @@ and an explanation of the underlying technique.
.. exn:: goal does not satisfy the expected preconditions.
:undocumented:
- .. tacv:: injection @term {? with @bindings_list} as {+ @intro_pattern}
- injection @num as {+ intro_pattern}
- injection as {+ intro_pattern}
- einjection @term {? with @bindings_list} as {+ intro_pattern}
- einjection @num as {+ intro_pattern}
- einjection as {+ intro_pattern}
+ .. tacv:: injection @term {? with @bindings_list} as {+ @simple_intropattern}
+ injection @num as {+ simple_intropattern}
+ injection as {+ simple_intropattern}
+ einjection @term {? with @bindings_list} as {+ simple_intropattern}
+ einjection @num as {+ simple_intropattern}
+ einjection as {+ simple_intropattern}
- These variants apply :n:`intros {+ @intro_pattern}` after the call to
+ These variants apply :n:`intros {+ @simple_intropattern}` after the call to
:tacn:`injection` or :tacn:`einjection` so that all equalities generated are moved in
- the context of hypotheses. The number of :n:`@intro_pattern` must not exceed
+ the context of hypotheses. The number of :n:`@simple_intropattern` must not exceed
the number of equalities newly generated. If it is smaller, fresh
- names are automatically generated to adjust the list of :n:`@intro_pattern`
+ names are automatically generated to adjust the list of :n:`@simple_intropattern`
to the number of new equalities. The original equality is erased if it
corresponds to a hypothesis.
@@ -2118,10 +2335,10 @@ and an explanation of the underlying technique.
This behaves as :n:`inversion` and then erases :n:`@ident` from the context.
-.. tacv:: inversion @ident as @intro_pattern
+.. tacv:: inversion @ident as @or_and_intropattern_loc
- This generally behaves as inversion but using names in :n:`@intro_pattern`
- for naming hypotheses. The :n:`@intro_pattern` must have the form
+ This generally behaves as inversion but using names in :n:`@or_and_intropattern_loc`
+ for naming hypotheses. The :n:`@or_and_intropattern_loc` must have the form
:n:`[p`:sub:`11` :n:`... p`:sub:`1n` :n:`| ... | p`:sub:`m1` :n:`... p`:sub:`mn` :n:`]`
with `m` being the number of constructors of the type of :n:`@ident`. Be
careful that the list must be of length `m` even if ``inversion`` discards
@@ -2153,12 +2370,12 @@ and an explanation of the underlying technique.
Goal forall l:list nat, contains0 (1 :: l) -> contains0 l.
intros l H; inversion H as [ | l' p Hl' [Heqp Heql'] ].
-.. tacv:: inversion @num as @intro_pattern
+.. tacv:: inversion @num as @or_and_intropattern_loc
This allows naming the hypotheses introduced by :n:`inversion @num` in the
context.
-.. tacv:: inversion_clear @ident as @intro_pattern
+.. tacv:: inversion_clear @ident as @or_and_intropattern_loc
This allows naming the hypotheses introduced by ``inversion_clear`` in the
context. Notice that hypothesis names can be provided as if ``inversion``
@@ -2170,7 +2387,7 @@ and an explanation of the underlying technique.
Let :n:`{+ @ident}` be identifiers in the local context. This tactic behaves as
generalizing :n:`{+ @ident}`, and then performing ``inversion``.
-.. tacv:: inversion @ident as @intro_pattern in {+ @ident}
+.. tacv:: inversion @ident as @or_and_intropattern_loc in {+ @ident}
This allows naming the hypotheses introduced in the context by
:n:`inversion @ident in {+ @ident}`.
@@ -2180,7 +2397,7 @@ and an explanation of the underlying technique.
Let :n:`{+ @ident}` be identifiers in the local context. This tactic behaves
as generalizing :n:`{+ @ident}`, and then performing ``inversion_clear``.
-.. tacv:: inversion_clear @ident as @intro_pattern in {+ @ident}
+.. tacv:: inversion_clear @ident as @or_and_intropattern_loc in {+ @ident}
This allows naming the hypotheses introduced in the context by
:n:`inversion_clear @ident in {+ @ident}`.
@@ -2192,7 +2409,7 @@ and an explanation of the underlying technique.
``inversion`` and then substitutes :n:`@ident` for the corresponding
:n:`@@term` in the goal.
-.. tacv:: dependent inversion @ident as @intro_pattern
+.. tacv:: dependent inversion @ident as @or_and_intropattern_loc
This allows naming the hypotheses introduced in the context by
:n:`dependent inversion @ident`.
@@ -2202,7 +2419,7 @@ and an explanation of the underlying technique.
Like ``dependent inversion``, except that :n:`@ident` is cleared from the
local context.
-.. tacv:: dependent inversion_clear @ident as @intro_pattern
+.. tacv:: dependent inversion_clear @ident as @or_and_intropattern_loc
This allows naming the hypotheses introduced in the context by
:n:`dependent inversion_clear @ident`.
@@ -2216,7 +2433,7 @@ and an explanation of the underlying technique.
then :n:`@term` must be of type :g:`I:forall (x:T), I x -> s'` where
:g:`s'` is the type of the goal.
-.. tacv:: dependent inversion @ident as @intro_pattern with @term
+.. tacv:: dependent inversion @ident as @or_and_intropattern_loc with @term
This allows naming the hypotheses introduced in the context by
:n:`dependent inversion @ident with @term`.
@@ -2226,7 +2443,7 @@ and an explanation of the underlying technique.
Like :tacn:`dependent inversion ... with ...` with but clears :n:`@ident` from the
local context.
-.. tacv:: dependent inversion_clear @ident as @intro_pattern with @term
+.. tacv:: dependent inversion_clear @ident as @or_and_intropattern_loc with @term
This allows naming the hypotheses introduced in the context by
:n:`dependent inversion_clear @ident with @term`.
@@ -2237,7 +2454,7 @@ and an explanation of the underlying technique.
It is a very primitive inversion tactic that derives all the necessary
equalities but it does not simplify the constraints as ``inversion`` does.
-.. tacv:: simple inversion @ident as @intro_pattern
+.. tacv:: simple inversion @ident as @or_and_intropattern_loc
This allows naming the hypotheses introduced in the context by
``simple inversion``.
@@ -3090,12 +3307,29 @@ the conversion in hypotheses :n:`{+ @ident}`.
:name: fold
This tactic applies to any goal. The term :n:`@term` is reduced using the
- ``red`` tactic. Every occurrence of the resulting :n:`@term` in the goal is
- then replaced by :n:`@term`.
+ :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
+
+ Goal ~0=0.
+ unfold not.
+ Fail progress fold not.
+ pattern (0 = 0).
+ fold not.
+
+ .. coqtop:: none
+
+ Abort.
-.. tacv:: fold {+ @term}
+ .. tacv:: fold {+ @term}
- Equivalent to :n:`fold @term ; ... ; fold @term`.
+ Equivalent to :n:`fold @term ; ... ; fold @term`.
.. tacn:: pattern @term
:name: pattern
@@ -3171,7 +3405,7 @@ Automation
:name: auto
This tactic implements a Prolog-like resolution procedure to solve the
- current goal. It first tries to solve the goal using the assumption
+ current goal. It first tries to solve the goal using the :tacn:`assumption`
tactic, then it reduces the goal to an atomic one using 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
@@ -3586,15 +3820,15 @@ The general command to add a hint to some databases :n:`{+ @ident}` is
the following. Beware, there is no operator precedence during parsing, one can
check with :cmd:`Print HintDb` to verify the current cut expression:
- .. productionlist:: `regexp`
- e : ident hint or instance identifier
- :| _ any hint
- :| e\|e′ disjunction
- :| e e′ sequence
- :| e * Kleene star
- :| emp empty
- :| eps epsilon
- :| ( e )
+ .. productionlist:: regexp
+ e : `ident` hint or instance identifier
+ : _ any hint
+ : `e` | `e` disjunction
+ : `e` `e` sequence
+ : `e` * Kleene star
+ : emp empty
+ : eps epsilon
+ : ( `e` )
The `emp` regexp does not match any search path while `eps`
matches the empty path. During proof search, the path of
@@ -4299,15 +4533,15 @@ Automating
.. _btauto_grammar:
- .. productionlist:: `sentence`
- t : x
- :∣ true
- :∣ false
- :∣ orb t1 t2
- :∣ andb t1 t2
- :∣ xorb t1 t2
- :∣ negb t
- :∣ if t1 then t2 else t3
+ .. productionlist:: sentence
+ t : `x`
+ : true
+ : false
+ : orb `t` `t`
+ : andb `t` `t`
+ : xorb `t` `t`
+ : negb `t`
+ : if `t` then `t` else `t`
Whenever the formula supplied is not a tautology, it also provides a
counter-example.
diff --git a/doc/sphinx/refman-preamble.sty b/doc/sphinx/refman-preamble.sty
index b4fc608e47..8f7b1bb1e8 100644
--- a/doc/sphinx/refman-preamble.sty
+++ b/doc/sphinx/refman-preamble.sty
@@ -56,27 +56,29 @@
\newcommand{\oddS}{\textsf{odd}_\textsf{S}}
\newcommand{\ovl}[1]{\overline{#1}}
\newcommand{\Pair}{\textsf{pair}}
+\newcommand{\plus}{\mathsf{plus}}
\newcommand{\Prod}{\textsf{prod}}
\newcommand{\Prop}{\textsf{Prop}}
\newcommand{\return}{\kw{return}}
\newcommand{\Set}{\textsf{Set}}
\newcommand{\si}{\textsf{if}}
\newcommand{\sinon}{\textsf{else}}
-\newcommand{\Sort}{\cal S}
+\newcommand{\Sort}{\mathcal{S}}
\newcommand{\Str}{\textsf{Stream}}
\newcommand{\Struct}{\kw{Struct}}
\newcommand{\subst}[3]{#1\{#2/#3\}}
\newcommand{\tl}{\textsf{tl}}
\newcommand{\tree}{\textsf{tree}}
+\newcommand{\trii}{\triangleright_\iota}
\newcommand{\true}{\textsf{true}}
\newcommand{\Type}{\textsf{Type}}
\newcommand{\unfold}{\textsf{unfold}}
\newcommand{\WEV}[3]{\mbox{$#1[] \vdash #2 \lra #3$}}
\newcommand{\WEVT}[3]{\mbox{$#1[] \vdash #2 \lra$}\\ \mbox{$ #3$}}
-\newcommand{\WF}[2]{{\cal W\!F}(#1)[#2]}
+\newcommand{\WF}[2]{{\mathcal{W\!F}}(#1)[#2]}
\newcommand{\WFE}[1]{\WF{E}{#1}}
-\newcommand{\WFT}[2]{#1[] \vdash {\cal W\!F}(#2)}
-\newcommand{\WFTWOLINES}[2]{{\cal W\!F}\begin{array}{l}(#1)\\\mbox{}[{#2}]\end{array}}
+\newcommand{\WFT}[2]{#1[] \vdash {\mathcal{W\!F}}(#2)}
+\newcommand{\WFTWOLINES}[2]{{\mathcal{W\!F}}\begin{array}{l}(#1)\\\mbox{}[{#2}]\end{array}}
\newcommand{\with}{\kw{with}}
\newcommand{\WS}[3]{#1[] \vdash #2 <: #3}
\newcommand{\WSE}[2]{\WS{E}{#1}{#2}}
diff --git a/doc/sphinx/user-extensions/syntax-extensions.rst b/doc/sphinx/user-extensions/syntax-extensions.rst
index 47afa5ba0c..105b0445fd 100644
--- a/doc/sphinx/user-extensions/syntax-extensions.rst
+++ b/doc/sphinx/user-extensions/syntax-extensions.rst
@@ -859,41 +859,41 @@ notations are given below. The optional :production:`scope` is described in
.. productionlist:: coq
notation : [Local] Notation `string` := `term` [`modifiers`] [: `scope`].
- : | [Local] Infix `string` := `qualid` [`modifiers`] [: `scope`].
- : | [Local] Reserved Notation `string` [`modifiers`] .
- : | Inductive `ind_body` [`decl_notation`] with … with `ind_body` [`decl_notation`].
- : | CoInductive `ind_body` [`decl_notation`] with … with `ind_body` [`decl_notation`].
- : | Fixpoint `fix_body` [`decl_notation`] with … with `fix_body` [`decl_notation`].
- : | CoFixpoint `cofix_body` [`decl_notation`] with … with `cofix_body` [`decl_notation`].
- : | [Local] Declare Custom Entry `ident`.
+ : [Local] Infix `string` := `qualid` [`modifiers`] [: `scope`].
+ : [Local] Reserved Notation `string` [`modifiers`] .
+ : Inductive `ind_body` [`decl_notation`] with … with `ind_body` [`decl_notation`].
+ : CoInductive `ind_body` [`decl_notation`] with … with `ind_body` [`decl_notation`].
+ : Fixpoint `fix_body` [`decl_notation`] with … with `fix_body` [`decl_notation`].
+ : CoFixpoint `cofix_body` [`decl_notation`] with … with `cofix_body` [`decl_notation`].
+ : [Local] Declare Custom Entry `ident`.
decl_notation : [where `string` := `term` [: `scope`] and … and `string` := `term` [: `scope`]].
modifiers : at level `num`
: in custom `ident`
: in custom `ident` at level `num`
- : | `ident` , … , `ident` at level `num` [`binderinterp`]
- : | `ident` , … , `ident` at next level [`binderinterp`]
- : | `ident` `explicit_subentry`
- : | left associativity
- : | right associativity
- : | no associativity
- : | only parsing
- : | only printing
- : | format `string`
+ : `ident` , … , `ident` at level `num` [`binderinterp`]
+ : `ident` , … , `ident` at next level [`binderinterp`]
+ : `ident` `explicit_subentry`
+ : left associativity
+ : right associativity
+ : no associativity
+ : only parsing
+ : only printing
+ : format `string`
explicit_subentry : ident
- : | global
- : | bigint
- : | [strict] pattern [at level `num`]
- : | binder
- : | closed binder
- : | constr [`binderinterp`]
- : | constr at level `num` [`binderinterp`]
- : | constr at next level [`binderinterp`]
- : | custom [`binderinterp`]
- : | custom at level `num` [`binderinterp`]
- : | custom at next level [`binderinterp`]
+ : global
+ : bigint
+ : [strict] pattern [at level `num`]
+ : binder
+ : closed binder
+ : constr [`binderinterp`]
+ : constr at level `num` [`binderinterp`]
+ : constr at next level [`binderinterp`]
+ : custom [`binderinterp`]
+ : custom at level `num` [`binderinterp`]
+ : custom at next level [`binderinterp`]
binderinterp : as ident
- : | as pattern
- : | as strict pattern
+ : as pattern
+ : as strict pattern
.. note:: No typing of the denoted expression is performed at definition
time. Type checking is done only at the time of use of the notation.
@@ -1496,12 +1496,13 @@ Numeral notations
function returns :g:`None`, or if the interpretation is registered
for only non-negative integers, and the given numeral is negative.
- .. exn:: @ident should go from Decimal.int to @type or (option @type). Instead of Decimal.int, the types Decimal.uint or Z could be used{? (require BinNums first)}.
+
+ .. exn:: @ident should go from Decimal.int to @type or (option @type). Instead of Decimal.int, the types Decimal.uint or Z or Int63.int could be used (you may need to require BinNums or Decimal or Int63 first).
The parsing function given to the :cmd:`Numeral Notation`
vernacular is not of the right type.
- .. exn:: @ident should go from @type to Decimal.int or (option Decimal.int). Instead of Decimal.int, the types Decimal.uint or Z could be used{? (require BinNums first)}.
+ .. exn:: @ident should go from @type to Decimal.int or (option Decimal.int). Instead of Decimal.int, the types Decimal.uint or Z or Int63.int could be used (you may need to require BinNums or Decimal or Int63 first).
The printing function given to the :cmd:`Numeral Notation`
vernacular is not of the right type.
@@ -1692,13 +1693,13 @@ Tactic notations allow to customize the syntax of tactics. They have the followi
tacn : Tactic Notation [`tactic_level`] [`prod_item` … `prod_item`] := `tactic`.
prod_item : `string` | `tactic_argument_type`(`ident`)
tactic_level : (at level `num`)
- tactic_argument_type : ident | simple_intropattern | reference
- : | hyp | hyp_list | ne_hyp_list
- : | constr | uconstr | constr_list | ne_constr_list
- : | integer | integer_list | ne_integer_list
- : | int_or_var | int_or_var_list | ne_int_or_var_list
- : | tactic | tactic0 | tactic1 | tactic2 | tactic3
- : | tactic4 | tactic5
+ tactic_argument_type : `ident` | `simple_intropattern` | `reference`
+ : `hyp` | `hyp_list` | `ne_hyp_list`
+ : `constr` | `uconstr` | `constr_list` | `ne_constr_list`
+ : `integer` | `integer_list` | `ne_integer_list`
+ : `int_or_var` | `int_or_var_list` | `ne_int_or_var_list`
+ : `tactic` | `tactic0` | `tactic1` | `tactic2` | `tactic3`
+ : `tactic4` | `tactic5`
.. cmd:: Tactic Notation {? (at level @level)} {+ @prod_item} := @tactic.
diff --git a/doc/stdlib/index-list.html.template b/doc/stdlib/index-list.html.template
index 51f94d7e5a..7b21b67eea 100644
--- a/doc/stdlib/index-list.html.template
+++ b/doc/stdlib/index-list.html.template
@@ -259,7 +259,7 @@ through the <tt>Require Import</tt> command.</p>
</dd>
<dt> <b>&nbsp;&nbsp;Cyclic</b>:
- Abstract and 31-bits-based cyclic arithmetic
+ Abstract and 63-bits-based cyclic arithmetic
</dt>
<dd>
theories/Numbers/Cyclic/Abstract/CyclicAxioms.v
@@ -268,11 +268,14 @@ through the <tt>Require Import</tt> command.</p>
theories/Numbers/Cyclic/Int31/Cyclic31.v
theories/Numbers/Cyclic/Int31/Ring31.v
theories/Numbers/Cyclic/Int31/Int31.v
+ theories/Numbers/Cyclic/Int63/Cyclic63.v
+ theories/Numbers/Cyclic/Int63/Int63.v
+ theories/Numbers/Cyclic/Int63/Ring63.v
theories/Numbers/Cyclic/ZModulo/ZModulo.v
</dd>
<dt> <b>&nbsp;&nbsp;Natural</b>:
- Abstract and 31-bits-words-based natural arithmetic
+ Abstract and 63-bits-words-based natural arithmetic
</dt>
<dd>
theories/Numbers/Natural/Abstract/NAdd.v
@@ -300,7 +303,7 @@ through the <tt>Require Import</tt> command.</p>
</dd>
<dt> <b>&nbsp;&nbsp;Integer</b>:
- Abstract and concrete (especially 31-bits-words-based) integer
+ Abstract and concrete (especially 63-bits-words-based) integer
arithmetic
</dt>
<dd>
@@ -618,5 +621,6 @@ through the <tt>Require Import</tt> command.</p>
theories/Compat/Coq87.v
theories/Compat/Coq88.v
theories/Compat/Coq89.v
+ theories/Compat/Coq810.v
</dd>
</dl>
diff --git a/dune b/dune
index a7264ba91e..95041512e2 100644
--- a/dune
+++ b/dune
@@ -5,7 +5,7 @@
(ocamlopt_flags -O3 -unbox-closures))
(ireport (flags :standard -rectypes -w -9-27-40+60)
(ocamlopt_flags :standard -O3 -unbox-closures -inlining-report))
- (ocaml408
+ (ocaml409
(flags :standard -strict-sequence -strict-formats -short-paths -keep-locs -rectypes -w -9-27+40+60 -warn-error -5 -alert --deprecated)))
; The _ profile could help factoring the above, however it doesn't
@@ -19,7 +19,7 @@
(deps
(source_tree theories)
(source_tree plugins))
- (action (with-stdout-to .vfiles.d (system "%{bin:coqdep} -dyndep opt -noglob -boot `find theories plugins -type f -name *.v`"))))
+ (action (with-stdout-to .vfiles.d (bash "%{bin:coqdep} -dyndep opt -noglob -boot `find theories plugins -type f -name *.v`"))))
(alias
(name vodeps)
@@ -35,7 +35,7 @@
(rule
(targets revision)
(deps (:rev-script dev/tools/make_git_revision.sh))
- (action (with-stdout-to revision (run %{rev-script}))))
+ (action (with-stdout-to revision (bash %{rev-script}))))
; Use summary.log as the target
(alias
diff --git a/engine/eConstr.ml b/engine/eConstr.ml
index 24d161d00a..8493119ee5 100644
--- a/engine/eConstr.ml
+++ b/engine/eConstr.ml
@@ -73,6 +73,7 @@ let mkFix f = of_kind (Fix f)
let mkCoFix f = of_kind (CoFix f)
let mkProj (p, c) = of_kind (Proj (p, c))
let mkArrow t1 t2 = of_kind (Prod (Anonymous, t1, t2))
+let mkInt i = of_kind (Int i)
let mkRef (gr,u) = let open GlobRef in match gr with
| ConstRef c -> mkConstU (c,u)
@@ -81,6 +82,7 @@ let mkRef (gr,u) = let open GlobRef in match gr with
| VarRef x -> mkVar x
let applist (f, arg) = mkApp (f, Array.of_list arg)
+let applistc f arg = mkApp (f, Array.of_list arg)
let isRel sigma c = match kind sigma c with Rel _ -> true | _ -> false
let isVar sigma c = match kind sigma c with Var _ -> true | _ -> false
@@ -328,7 +330,7 @@ let iter_with_full_binders sigma g f n c =
let open Context.Rel.Declaration in
match kind sigma c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> ()
+ | Construct _ | Int _) -> ()
| Cast (c,_,t) -> f n c; f n t
| Prod (na,t,c) -> f n t; f (g (LocalAssum (na, t)) n) c
| Lambda (na,t,c) -> f n t; f (g (LocalAssum (na, t)) n) c
diff --git a/engine/eConstr.mli b/engine/eConstr.mli
index 49cbc4d7e5..2f4cf7d5d0 100644
--- a/engine/eConstr.mli
+++ b/engine/eConstr.mli
@@ -124,10 +124,12 @@ val mkCase : case_info * t * t * t array -> t
val mkFix : (t, t) pfixpoint -> t
val mkCoFix : (t, t) pcofixpoint -> t
val mkArrow : t -> t -> t
+val mkInt : Uint63.t -> t
val mkRef : GlobRef.t * EInstance.t -> t
val applist : t * t list -> t
+val applistc : t -> t list -> t
val mkProd_or_LetIn : rel_declaration -> t -> t
val mkLambda_or_LetIn : rel_declaration -> t -> t
diff --git a/engine/namegen.ml b/engine/namegen.ml
index 018eca1ba2..294b61fd3d 100644
--- a/engine/namegen.ml
+++ b/engine/namegen.ml
@@ -118,7 +118,7 @@ let head_name sigma c = (* Find the head constant of a constr if any *)
Some (Nametab.basename_of_global (global_of_constr c))
| Fix ((_,i),(lna,_,_)) | CoFix (i,(lna,_,_)) ->
Some (match lna.(i) with Name id -> id | _ -> assert false)
- | Sort _ | Rel _ | Meta _|Evar _|Case (_, _, _, _) -> None
+ | Sort _ | Rel _ | Meta _|Evar _|Case (_, _, _, _) | Int _ -> None
in
hdrec c
@@ -163,6 +163,7 @@ let hdchar env sigma c =
lowercase_first_char id
| Evar _ (* We could do better... *)
| Meta _ | Case (_, _, _, _) -> "y"
+ | Int _ -> "i"
in
hdrec 0 c
diff --git a/engine/proofview.ml b/engine/proofview.ml
index cf4224bbdb..d4ad53ff5f 100644
--- a/engine/proofview.ml
+++ b/engine/proofview.ml
@@ -39,7 +39,7 @@ let proofview p =
let compact el ({ solution } as pv) =
let nf c = Evarutil.nf_evar solution c in
- let nf0 c = EConstr.(to_constr solution (of_constr c)) in
+ let nf0 c = EConstr.(to_constr ~abort_on_undefined_evars:false solution (of_constr c)) in
let size = Evd.fold (fun _ _ i -> i+1) solution 0 in
let new_el = List.map (fun (t,ty) -> nf t, nf ty) el in
let pruned_solution = Evd.drop_all_defined solution in
diff --git a/engine/termops.ml b/engine/termops.ml
index 137770d8f0..579100ad4c 100644
--- a/engine/termops.ml
+++ b/engine/termops.ml
@@ -38,7 +38,7 @@ let set_print_constr f = term_printer := f
module EvMap = Evar.Map
-let pr_evar_suggested_name evk sigma =
+let evar_suggested_name evk sigma =
let open Evd in
let base_id evk' evi =
match evar_ident evk' sigma with
@@ -67,7 +67,7 @@ let pr_existential_key sigma evk =
let open Evd in
match evar_ident evk sigma with
| None ->
- str "?" ++ Id.print (pr_evar_suggested_name evk sigma)
+ str "?" ++ Id.print (evar_suggested_name evk sigma)
| Some id ->
str "?" ++ Id.print id
@@ -600,7 +600,7 @@ let map_constr_with_binders_left_to_right sigma g f l c =
let open EConstr in
match EConstr.kind sigma c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> c
+ | Construct _ | Int _) -> c
| Cast (b,k,t) ->
let b' = f l b in
let t' = f l t in
@@ -681,7 +681,7 @@ let map_constr_with_full_binders_gen userview sigma g f l cstr =
let open EConstr in
match EConstr.kind sigma cstr with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> cstr
+ | Construct _ | Int _) -> cstr
| Cast (c,k, t) ->
let c' = f l c in
let t' = f l t in
diff --git a/engine/termops.mli b/engine/termops.mli
index 7920af8e0e..61a6ec1cd6 100644
--- a/engine/termops.mli
+++ b/engine/termops.mli
@@ -304,7 +304,7 @@ open Evd
val pr_existential_key : evar_map -> Evar.t -> Pp.t
-val pr_evar_suggested_name : Evar.t -> evar_map -> Id.t
+val evar_suggested_name : Evar.t -> evar_map -> Id.t
val pr_evar_info : env -> evar_map -> evar_info -> Pp.t
val pr_evar_constraints : evar_map -> evar_constraint list -> Pp.t
diff --git a/engine/uState.ml b/engine/uState.ml
index 6969d2ba44..430a3a2fd9 100644
--- a/engine/uState.ml
+++ b/engine/uState.ml
@@ -12,6 +12,7 @@ open Pp
open CErrors
open Util
open Names
+open Univ
module UNameMap = Names.Id.Map
@@ -24,12 +25,12 @@ module UPairSet = UnivMinim.UPairSet
(* 2nd part used to check consistency on the fly. *)
type t =
- { uctx_names : UnivNames.universe_binders * uinfo Univ.LMap.t;
- uctx_local : Univ.ContextSet.t; (** The local context of variables *)
- uctx_seff_univs : Univ.LSet.t; (** Local universes used through private constants *)
+ { uctx_names : UnivNames.universe_binders * uinfo LMap.t;
+ uctx_local : ContextSet.t; (** The local context of variables *)
+ uctx_seff_univs : LSet.t; (** Local universes used through private constants *)
uctx_univ_variables : UnivSubst.universe_opt_subst;
(** The local universes that are unification variables *)
- uctx_univ_algebraic : Univ.LSet.t;
+ uctx_univ_algebraic : LSet.t;
(** The subset of unification variables that can be instantiated with
algebraic universes as they appear in inferred types only. *)
uctx_universes : UGraph.t; (** The current graph extended with the local constraints *)
@@ -38,11 +39,11 @@ type t =
}
let empty =
- { uctx_names = UNameMap.empty, Univ.LMap.empty;
- uctx_local = Univ.ContextSet.empty;
- uctx_seff_univs = Univ.LSet.empty;
- uctx_univ_variables = Univ.LMap.empty;
- uctx_univ_algebraic = Univ.LSet.empty;
+ { uctx_names = UNameMap.empty, LMap.empty;
+ uctx_local = ContextSet.empty;
+ uctx_seff_univs = LSet.empty;
+ uctx_univ_variables = LMap.empty;
+ uctx_univ_algebraic = LSet.empty;
uctx_universes = UGraph.initial_universes;
uctx_initial_universes = UGraph.initial_universes;
uctx_weak_constraints = UPairSet.empty; }
@@ -52,8 +53,8 @@ let make u =
uctx_universes = u; uctx_initial_universes = u}
let is_empty ctx =
- Univ.ContextSet.is_empty ctx.uctx_local &&
- Univ.LMap.is_empty ctx.uctx_univ_variables
+ ContextSet.is_empty ctx.uctx_local &&
+ LMap.is_empty ctx.uctx_univ_variables
let uname_union s t =
if s == t then s
@@ -67,29 +68,29 @@ let union ctx ctx' =
if ctx == ctx' then ctx
else if is_empty ctx' then ctx
else
- let local = Univ.ContextSet.union ctx.uctx_local ctx'.uctx_local in
- let seff = Univ.LSet.union ctx.uctx_seff_univs ctx'.uctx_seff_univs in
+ let local = ContextSet.union ctx.uctx_local ctx'.uctx_local in
+ let seff = LSet.union ctx.uctx_seff_univs ctx'.uctx_seff_univs in
let names = uname_union (fst ctx.uctx_names) (fst ctx'.uctx_names) in
- let newus = Univ.LSet.diff (Univ.ContextSet.levels ctx'.uctx_local)
- (Univ.ContextSet.levels ctx.uctx_local) in
- let newus = Univ.LSet.diff newus (Univ.LMap.domain ctx.uctx_univ_variables) in
+ let newus = LSet.diff (ContextSet.levels ctx'.uctx_local)
+ (ContextSet.levels ctx.uctx_local) in
+ let newus = LSet.diff newus (LMap.domain ctx.uctx_univ_variables) in
let weak = UPairSet.union ctx.uctx_weak_constraints ctx'.uctx_weak_constraints in
let declarenew g =
- Univ.LSet.fold (fun u g -> UGraph.add_universe u false g) newus g
+ LSet.fold (fun u g -> UGraph.add_universe u false g) newus g
in
- let names_rev = Univ.LMap.union (snd ctx.uctx_names) (snd ctx'.uctx_names) in
+ let names_rev = LMap.union (snd ctx.uctx_names) (snd ctx'.uctx_names) in
{ uctx_names = (names, names_rev);
uctx_local = local;
uctx_seff_univs = seff;
uctx_univ_variables =
- Univ.LMap.subst_union ctx.uctx_univ_variables ctx'.uctx_univ_variables;
+ LMap.subst_union ctx.uctx_univ_variables ctx'.uctx_univ_variables;
uctx_univ_algebraic =
- Univ.LSet.union ctx.uctx_univ_algebraic ctx'.uctx_univ_algebraic;
+ LSet.union ctx.uctx_univ_algebraic ctx'.uctx_univ_algebraic;
uctx_initial_universes = declarenew ctx.uctx_initial_universes;
uctx_universes =
(if local == ctx.uctx_local then ctx.uctx_universes
else
- let cstrsr = Univ.ContextSet.constraints ctx'.uctx_local in
+ let cstrsr = ContextSet.constraints ctx'.uctx_local in
UGraph.merge_constraints cstrsr (declarenew ctx.uctx_universes));
uctx_weak_constraints = weak}
@@ -97,14 +98,14 @@ let context_set ctx = ctx.uctx_local
let constraints ctx = snd ctx.uctx_local
-let context ctx = Univ.ContextSet.to_context ctx.uctx_local
+let context ctx = ContextSet.to_context ctx.uctx_local
let const_univ_entry ~poly uctx =
let open Entries in
if poly then
let (binders, _) = uctx.uctx_names in
let uctx = context uctx in
- let nas = UnivNames.compute_instance_binders (Univ.UContext.instance uctx) binders in
+ let nas = UnivNames.compute_instance_binders (UContext.instance uctx) binders in
Polymorphic_const_entry (nas, uctx)
else Monomorphic_const_entry (context_set uctx)
@@ -114,7 +115,7 @@ let ind_univ_entry ~poly uctx =
if poly then
let (binders, _) = uctx.uctx_names in
let uctx = context uctx in
- let nas = UnivNames.compute_instance_binders (Univ.UContext.instance uctx) binders in
+ let nas = UnivNames.compute_instance_binders (UContext.instance uctx) binders in
Polymorphic_ind_entry (nas, uctx)
else Monomorphic_ind_entry (context_set uctx)
@@ -132,19 +133,19 @@ let add_uctx_names ?loc s l (names, names_rev) =
if UNameMap.mem s names
then user_err ?loc ~hdr:"add_uctx_names"
Pp.(str "Universe " ++ Names.Id.print s ++ str" already bound.");
- (UNameMap.add s l names, Univ.LMap.add l { uname = Some s; uloc = loc } names_rev)
+ (UNameMap.add s l names, LMap.add l { uname = Some s; uloc = loc } names_rev)
let add_uctx_loc l loc (names, names_rev) =
match loc with
| None -> (names, names_rev)
- | Some _ -> (names, Univ.LMap.add l { uname = None; uloc = loc } names_rev)
+ | Some _ -> (names, LMap.add l { uname = None; uloc = loc } names_rev)
let of_binders b =
let ctx = empty in
let rmap =
UNameMap.fold (fun id l rmap ->
- Univ.LMap.add l { uname = Some id; uloc = None } rmap)
- b Univ.LMap.empty
+ LMap.add l { uname = Some id; uloc = None } rmap)
+ b LMap.empty
in
{ ctx with uctx_names = b, rmap }
@@ -157,7 +158,6 @@ let invent_name (named,cnt) u =
aux cnt
let universe_binders ctx =
- let open Univ in
let named, rev = ctx.uctx_names in
let named, _ = LSet.fold (fun u named ->
match LMap.find u rev with
@@ -169,7 +169,7 @@ let universe_binders ctx =
named
let instantiate_variable l b v =
- try v := Univ.LMap.set l (Some b) !v
+ try v := LMap.set l (Some b) !v
with Not_found -> assert false
exception UniversesDiffer
@@ -177,7 +177,6 @@ exception UniversesDiffer
let drop_weak_constraints = ref false
let process_universe_constraints ctx cstrs =
- let open Univ in
let open UnivSubst in
let open UnivProblem in
let univs = ctx.uctx_universes in
@@ -190,9 +189,9 @@ let process_universe_constraints ctx cstrs =
| UEq (u, v) -> UEq (subst_univs_universe normalize u, subst_univs_universe normalize v)
| ULe (u, v) -> ULe (subst_univs_universe normalize u, subst_univs_universe normalize v)
in
- let is_local l = Univ.LMap.mem l !vars in
+ let is_local l = LMap.mem l !vars in
let varinfo x =
- match Univ.Universe.level x with
+ match Universe.level x with
| None -> Inl x
| Some l -> Inr l
in
@@ -206,27 +205,27 @@ let process_universe_constraints ctx cstrs =
else if not (UGraph.check_eq_level univs l' r') then
(* Two rigid/global levels, none of them being local,
one of them being Prop/Set, disallow *)
- if Univ.Level.is_small l' || Univ.Level.is_small r' then
- raise (Univ.UniverseInconsistency (Univ.Eq, l, r, None))
+ if Level.is_small l' || Level.is_small r' then
+ raise (UniverseInconsistency (Eq, l, r, None))
else if fo then
raise UniversesDiffer
in
- Univ.enforce_eq_level l' r' local
+ enforce_eq_level l' r' local
in
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 = Univ.LSet.mem l ctx.uctx_univ_algebraic in
- let inst = Univ.univ_level_rem l r r in
+ let alg = LSet.mem l ctx.uctx_univ_algebraic in
+ let inst = univ_level_rem l r r in
if alg then (instantiate_variable l inst vars; local)
else
- let lu = Univ.Universe.make l in
- if Univ.univ_level_mem l r then
- Univ.enforce_leq inst lu local
- else raise (Univ.UniverseInconsistency (Univ.Eq, lu, r, None))
+ let lu = Universe.make l in
+ if univ_level_mem l r then
+ enforce_leq inst lu local
+ else raise (UniverseInconsistency (Eq, lu, r, None))
| Inl _, Inl _ (* both are algebraic *) ->
if UGraph.check_eq univs l r then local
- else raise (Univ.UniverseInconsistency (Univ.Eq, l, r, None))
+ else raise (UniverseInconsistency (Eq, l, r, None))
in
let unify_universes cst local =
let cst = nf_constraint cst in
@@ -237,29 +236,29 @@ let process_universe_constraints ctx cstrs =
if UGraph.check_leq univs l r then
(* Keep Prop/Set <= var around if var might be instantiated by prop or set
later. *)
- match Univ.Universe.level l, Univ.Universe.level r with
+ match Universe.level l, Universe.level r with
| Some l, Some r ->
- Univ.Constraint.add (l, Univ.Le, r) local
+ Constraint.add (l, Le, r) local
| _ -> local
else
- begin match Univ.Universe.level r with
+ begin match Universe.level r with
| None -> user_err Pp.(str "Algebraic universe on the right")
| Some r' ->
- if Univ.Level.is_small r' then
- if not (Univ.Universe.is_levels l)
+ if Level.is_small r' then
+ if not (Universe.is_levels l)
then
- raise (Univ.UniverseInconsistency (Univ.Le, l, r, None))
+ raise (UniverseInconsistency (Le, l, r, None))
else
- let levels = Univ.Universe.levels l in
+ let levels = Universe.levels l in
let fold l' local =
- let l = Univ.Universe.make l' in
- if Univ.Level.is_small l' || is_local l' then
+ let l = Universe.make l' in
+ if Level.is_small l' || is_local l' then
equalize_variables false l l' r r' local
- else raise (Univ.UniverseInconsistency (Univ.Le, l, r, None))
+ else raise (UniverseInconsistency (Le, l, r, None))
in
- Univ.LSet.fold fold levels local
+ LSet.fold fold levels local
else
- Univ.enforce_leq l r local
+ enforce_leq l r local
end
| ULub (l, r) ->
equalize_variables true (Universe.make l) l (Universe.make r) r local
@@ -268,26 +267,26 @@ let process_universe_constraints ctx cstrs =
| UEq (l, r) -> equalize_universes l r local
in
let local =
- UnivProblem.Set.fold unify_universes cstrs Univ.Constraint.empty
+ UnivProblem.Set.fold unify_universes cstrs Constraint.empty
in
!vars, !weak, local
let add_constraints ctx cstrs =
let univs, local = ctx.uctx_local in
- let cstrs' = Univ.Constraint.fold (fun (l,d,r) acc ->
- let l = Univ.Universe.make l and r = Univ.Universe.make r 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
match d with
- | Univ.Lt ->
- ULe (Univ.Universe.super l, r)
- | Univ.Le -> ULe (l, r)
- | Univ.Eq -> UEq (l, r)
+ | Lt ->
+ ULe (Universe.super l, r)
+ | Le -> ULe (l, r)
+ | Eq -> UEq (l, r)
in UnivProblem.Set.add cstr' acc)
cstrs UnivProblem.Set.empty
in
let vars, weak, local' = process_universe_constraints ctx cstrs' in
{ ctx with
- uctx_local = (univs, Univ.Constraint.union local local');
+ uctx_local = (univs, Constraint.union local local');
uctx_univ_variables = vars;
uctx_universes = UGraph.merge_constraints local' ctx.uctx_universes;
uctx_weak_constraints = weak; }
@@ -299,7 +298,7 @@ let add_universe_constraints ctx cstrs =
let univs, local = ctx.uctx_local in
let vars, weak, local' = process_universe_constraints ctx cstrs in
{ ctx with
- uctx_local = (univs, Univ.Constraint.union local local');
+ uctx_local = (univs, Constraint.union local local');
uctx_univ_variables = vars;
uctx_universes = UGraph.merge_constraints local' ctx.uctx_universes;
uctx_weak_constraints = weak; }
@@ -307,14 +306,14 @@ let add_universe_constraints ctx cstrs =
let constrain_variables diff ctx =
let univs, local = ctx.uctx_local in
let univs, vars, local =
- Univ.LSet.fold
+ LSet.fold
(fun l (univs, vars, cstrs) ->
try
- match Univ.LMap.find l vars with
+ match LMap.find l vars with
| Some u ->
- (Univ.LSet.add l univs,
- Univ.LMap.remove l vars,
- Univ.Constraint.add (l, Univ.Eq, Option.get (Univ.Universe.level u)) cstrs)
+ (LSet.add l univs,
+ LMap.remove l vars,
+ 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.uctx_univ_variables, local)
@@ -324,14 +323,14 @@ let constrain_variables diff ctx =
let qualid_of_level uctx =
let map, map_rev = uctx.uctx_names in
fun l ->
- try Some (Libnames.qualid_of_ident (Option.get (Univ.LMap.find l map_rev).uname))
+ try Some (Libnames.qualid_of_ident (Option.get (LMap.find l map_rev).uname))
with Not_found | Option.IsNone ->
UnivNames.qualid_of_level l
let pr_uctx_level uctx l =
match qualid_of_level uctx l with
| Some qid -> Libnames.pr_qualid qid
- | None -> Univ.Level.pr l
+ | None -> Level.pr l
type ('a, 'b) gen_universe_decl = {
univdecl_instance : 'a; (* Declared universes *)
@@ -340,16 +339,15 @@ type ('a, 'b) gen_universe_decl = {
univdecl_extensible_constraints : bool (* Can new constraints be added *) }
type universe_decl =
- (lident list, Univ.Constraint.t) gen_universe_decl
+ (lident list, Constraint.t) gen_universe_decl
let default_univ_decl =
{ univdecl_instance = [];
univdecl_extensible_instance = true;
- univdecl_constraints = Univ.Constraint.empty;
+ univdecl_constraints = Constraint.empty;
univdecl_extensible_constraints = true }
let error_unbound_universes left uctx =
- let open Univ in
let n = LSet.cardinal left in
let loc =
try
@@ -365,7 +363,6 @@ let error_unbound_universes left uctx =
str" unbound."))
let universe_context ~names ~extensible uctx =
- let open Univ in
let levels = ContextSet.levels uctx.uctx_local in
let newinst, left =
List.fold_right
@@ -388,7 +385,6 @@ let universe_context ~names ~extensible uctx =
let check_universe_context_set ~names ~extensible uctx =
if extensible then ()
else
- let open Univ in
let left = List.fold_left (fun left { CAst.loc; v = id } ->
let l =
try UNameMap.find id (fst uctx.uctx_names)
@@ -415,7 +411,7 @@ let check_mono_univ_decl uctx decl =
if not decl.univdecl_extensible_constraints then
check_implication uctx
decl.univdecl_constraints
- (Univ.ContextSet.constraints uctx.uctx_local);
+ (ContextSet.constraints uctx.uctx_local);
uctx.uctx_local
let check_univ_decl ~poly uctx decl =
@@ -425,7 +421,7 @@ let check_univ_decl ~poly uctx decl =
if poly then
let (binders, _) = uctx.uctx_names in
let uctx = universe_context ~names ~extensible uctx in
- let nas = UnivNames.compute_instance_binders (Univ.UContext.instance uctx) binders in
+ let nas = UnivNames.compute_instance_binders (UContext.instance uctx) binders in
Entries.Polymorphic_const_entry (nas, uctx)
else
let () = check_universe_context_set ~names ~extensible uctx in
@@ -434,11 +430,10 @@ let check_univ_decl ~poly uctx decl =
if not decl.univdecl_extensible_constraints then
check_implication uctx
decl.univdecl_constraints
- (Univ.ContextSet.constraints uctx.uctx_local);
+ (ContextSet.constraints uctx.uctx_local);
ctx
let restrict_universe_context (univs, csts) keep =
- let open Univ in
let removed = LSet.diff univs keep in
if LSet.is_empty removed then univs, csts
else
@@ -453,8 +448,8 @@ let restrict_universe_context (univs, csts) keep =
(LSet.inter univs keep, csts)
let restrict ctx vars =
- let vars = Univ.LSet.union vars ctx.uctx_seff_univs in
- let vars = Names.Id.Map.fold (fun na l vars -> Univ.LSet.add l vars)
+ let vars = LSet.union vars ctx.uctx_seff_univs in
+ let vars = Names.Id.Map.fold (fun na l vars -> LSet.add l vars)
(fst ctx.uctx_names) vars
in
let uctx' = restrict_universe_context ctx.uctx_local vars in
@@ -465,7 +460,7 @@ let demote_seff_univs entry uctx =
match entry.const_entry_universes with
| Polymorphic_const_entry _ -> uctx
| Monomorphic_const_entry (univs, _) ->
- let seff = Univ.LSet.union uctx.uctx_seff_univs univs in
+ let seff = LSet.union uctx.uctx_seff_univs univs in
{ uctx with uctx_seff_univs = seff }
type rigid =
@@ -483,7 +478,6 @@ let univ_flexible_alg = UnivFlexible true
or defined separately. In the later case, there is no extension,
see [emit_side_effects] for example. *)
let merge ?loc ~sideff ~extend rigid uctx ctx' =
- let open Univ in
let levels = ContextSet.levels ctx' in
let uctx =
if not extend then uctx else
@@ -527,7 +521,7 @@ let merge ?loc ~sideff ~extend rigid uctx ctx' =
uctx_initial_universes = initial }
let merge_subst uctx s =
- { uctx with uctx_univ_variables = Univ.LMap.subst_union uctx.uctx_univ_variables s }
+ { uctx with uctx_univ_variables = LMap.subst_union uctx.uctx_univ_variables s }
let emit_side_effects eff u =
let uctxs = Safe_typing.universes_of_private eff in
@@ -536,14 +530,14 @@ let emit_side_effects eff u =
let new_univ_variable ?loc rigid name
({ uctx_local = ctx; uctx_univ_variables = uvars; uctx_univ_algebraic = avars} as uctx) =
let u = UnivGen.fresh_level () in
- let ctx' = Univ.ContextSet.add_universe u ctx in
+ let ctx' = ContextSet.add_universe u ctx in
let uctx', pred =
match rigid with
| UnivRigid -> uctx, true
| UnivFlexible b ->
- let uvars' = Univ.LMap.add u None uvars in
+ let uvars' = LMap.add u None uvars in
if b then {uctx with uctx_univ_variables = uvars';
- uctx_univ_algebraic = Univ.LSet.add u avars}, false
+ uctx_univ_algebraic = LSet.add u avars}, false
else {uctx with uctx_univ_variables = uvars'}, false
in
let names =
@@ -574,12 +568,11 @@ let add_global_univ uctx u =
let univs =
UGraph.add_universe u true uctx.uctx_universes
in
- { uctx with uctx_local = Univ.ContextSet.add_universe u uctx.uctx_local;
+ { uctx with uctx_local = ContextSet.add_universe u uctx.uctx_local;
uctx_initial_universes = initial;
uctx_universes = univs }
let make_flexible_variable ctx ~algebraic u =
- let open Univ in
let {uctx_local = cstrs; uctx_univ_variables = uvars;
uctx_univ_algebraic = avars; uctx_universes=g; } = ctx in
assert (try LMap.find u uvars == None with Not_found -> true);
@@ -608,48 +601,47 @@ let make_flexible_variable ctx ~algebraic u =
uctx_univ_algebraic = avars'}
let make_nonalgebraic_variable ctx u =
- { ctx with uctx_univ_algebraic = Univ.LSet.remove u ctx.uctx_univ_algebraic }
+ { ctx with uctx_univ_algebraic = LSet.remove u ctx.uctx_univ_algebraic }
let make_flexible_nonalgebraic ctx =
- {ctx with uctx_univ_algebraic = Univ.LSet.empty}
+ {ctx with uctx_univ_algebraic = LSet.empty}
let is_sort_variable uctx s =
match s with
| Sorts.Type u ->
- (match Univ.universe_level u with
+ (match universe_level u with
| Some l as x ->
- if Univ.LSet.mem l (Univ.ContextSet.levels uctx.uctx_local) then x
+ if LSet.mem l (ContextSet.levels uctx.uctx_local) then x
else None
| None -> None)
| _ -> None
let subst_univs_context_with_def def usubst (ctx, cst) =
- (Univ.LSet.diff ctx def, UnivSubst.subst_univs_constraints usubst cst)
+ (LSet.diff ctx def, UnivSubst.subst_univs_constraints usubst cst)
let is_trivial_leq (l,d,r) =
- Univ.Level.is_prop l && (d == Univ.Le || (d == Univ.Lt && Univ.Level.is_set r))
+ Level.is_prop l && (d == Le || (d == Lt && Level.is_set r))
(* Prop < i <-> Set+1 <= i <-> Set < i *)
let translate_cstr (l,d,r as cstr) =
- let open Univ in
- if Level.equal Level.prop l && d == Univ.Lt && not (Level.equal Level.set r) then
+ if Level.equal Level.prop l && d == Lt && not (Level.equal Level.set r) then
(Level.set, d, r)
else cstr
let refresh_constraints univs (ctx, cstrs) =
let cstrs', univs' =
- Univ.Constraint.fold (fun c (cstrs', univs as acc) ->
+ Constraint.fold (fun c (cstrs', univs as acc) ->
let c = translate_cstr c in
if is_trivial_leq c then acc
- else (Univ.Constraint.add c cstrs', UGraph.enforce_constraint c univs))
- cstrs (Univ.Constraint.empty, univs)
+ else (Constraint.add c cstrs', UGraph.enforce_constraint c univs))
+ cstrs (Constraint.empty, univs)
in ((ctx, cstrs'), univs')
let normalize_variables uctx =
let normalized_variables, def, subst =
UnivSubst.normalize_univ_variables uctx.uctx_univ_variables
in
- let ctx_local = subst_univs_context_with_def def (Univ.make_subst subst) uctx.uctx_local in
+ let ctx_local = subst_univs_context_with_def def (make_subst subst) uctx.uctx_local in
let ctx_local', univs = refresh_constraints uctx.uctx_initial_universes ctx_local in
subst, { uctx with uctx_local = ctx_local';
uctx_univ_variables = normalized_variables;
@@ -657,17 +649,17 @@ let normalize_variables uctx =
let abstract_undefined_variables uctx =
let vars' =
- Univ.LMap.fold (fun u v acc ->
- if v == None then Univ.LSet.remove u acc
+ LMap.fold (fun u v acc ->
+ if v == None then LSet.remove u acc
else acc)
uctx.uctx_univ_variables uctx.uctx_univ_algebraic
- in { uctx with uctx_local = Univ.ContextSet.empty;
+ in { uctx with uctx_local = ContextSet.empty;
uctx_univ_algebraic = vars' }
let fix_undefined_variables uctx =
let algs', vars' =
- Univ.LMap.fold (fun u v (algs, vars as acc) ->
- if v == None then (Univ.LSet.remove u algs, Univ.LMap.remove u vars)
+ LMap.fold (fun u v (algs, vars as acc) ->
+ if v == None then (LSet.remove u algs, LMap.remove u vars)
else acc)
uctx.uctx_univ_variables
(uctx.uctx_univ_algebraic, uctx.uctx_univ_variables)
@@ -677,20 +669,20 @@ let fix_undefined_variables uctx =
let refresh_undefined_univ_variables uctx =
let subst, ctx' = UnivGen.fresh_universe_context_set_instance uctx.uctx_local in
- let subst_fn u = Univ.subst_univs_level_level subst u in
- let alg = Univ.LSet.fold (fun u acc -> Univ.LSet.add (subst_fn u) acc)
- uctx.uctx_univ_algebraic Univ.LSet.empty
+ let subst_fn u = subst_univs_level_level subst u in
+ let alg = LSet.fold (fun u acc -> LSet.add (subst_fn u) acc)
+ uctx.uctx_univ_algebraic LSet.empty
in
let vars =
- Univ.LMap.fold
+ LMap.fold
(fun u v acc ->
- Univ.LMap.add (subst_fn u)
- (Option.map (Univ.subst_univs_level_universe subst) v) acc)
- uctx.uctx_univ_variables Univ.LMap.empty
+ LMap.add (subst_fn u)
+ (Option.map (subst_univs_level_universe subst) v) acc)
+ uctx.uctx_univ_variables LMap.empty
in
let weak = UPairSet.fold (fun (u,v) acc -> UPairSet.add (subst_fn u, subst_fn v) acc) uctx.uctx_weak_constraints UPairSet.empty in
- let declare g = Univ.LSet.fold (fun u g -> UGraph.add_universe u false g)
- (Univ.ContextSet.levels ctx') g in
+ let declare g = LSet.fold (fun u g -> UGraph.add_universe u false g)
+ (ContextSet.levels ctx') g in
let initial = declare uctx.uctx_initial_universes in
let univs = declare UGraph.initial_universes in
let uctx' = {uctx_names = uctx.uctx_names;
@@ -708,7 +700,7 @@ let minimize uctx =
normalize_context_set uctx.uctx_universes uctx.uctx_local uctx.uctx_univ_variables
uctx.uctx_univ_algebraic uctx.uctx_weak_constraints
in
- if Univ.ContextSet.equal us' uctx.uctx_local then uctx
+ if ContextSet.equal us' uctx.uctx_local then uctx
else
let us', universes =
refresh_constraints uctx.uctx_initial_universes us'
diff --git a/ide/fake_ide.ml b/ide/fake_ide.ml
index 8b0c736f50..4e26cb6095 100644
--- a/ide/fake_ide.ml
+++ b/ide/fake_ide.ml
@@ -241,6 +241,9 @@ let eval_print l coq =
| [ Tok(_,"ADD"); Top [Tok(_,name)]; Tok(_,phrase) ] ->
let eid, tip = add_sentence ~name phrase in
after_add (base_eval_call (add ((phrase,eid),(tip,true))) coq)
+ | [ Tok(_,"FAILADD"); Tok(_,phrase) ] ->
+ let eid, tip = add_sentence phrase in
+ after_fail coq (base_eval_call ~fail:false (add ((phrase,eid),(tip,true))) coq)
| [ Tok(_,"GOALS"); ] ->
eval_call (goals ()) coq
| [ Tok(_,"FAILGOALS"); ] ->
@@ -267,7 +270,8 @@ let eval_print l coq =
prerr_endline "Quitting fake_ide";
exit 0
| Tok("#[^\n]*",_) :: _ -> ()
- | _ -> error "syntax error"
+ | Tok(s,_) :: _ -> error ("syntax error at " ^ s)
+ | _ -> error ("syntax error")
let grammar =
let open Parser in
@@ -275,6 +279,7 @@ let grammar =
let eat_phrase = eat_balanced '{' in
Alt
[ Seq [Item (eat_rex "ADD"); Opt (Item eat_id); Item eat_phrase]
+ ; Seq [Item (eat_rex "FAILADD"); Item eat_phrase]
; Seq [Item (eat_rex "EDIT_AT"); Item eat_id]
; Seq [Item (eat_rex "QUERY"); Opt (Item eat_id); Item eat_phrase]
; Seq [Item (eat_rex "WAIT")]
diff --git a/ide/idetop.ml b/ide/idetop.ml
index 716a942d5c..e157696294 100644
--- a/ide/idetop.ml
+++ b/ide/idetop.ml
@@ -64,11 +64,19 @@ let is_known_option cmd = match Vernacprop.under_control cmd with
(** Check whether a command is forbidden in the IDE *)
-let ide_cmd_checks ~id {CAst.loc;v=ast} =
- let user_error s = CErrors.user_err ?loc ~hdr:"IDE" (str s) in
- let warn msg = Feedback.(feedback ~id (Message (Warning, loc, strbrk msg))) in
+let ide_cmd_checks ~last_valid {CAst.loc;v=ast} =
+ let user_error s =
+ try CErrors.user_err ?loc ~hdr:"IDE" (str s)
+ with e ->
+ let (e, info) = CErrors.push e in
+ let info = Stateid.add info ~valid:last_valid Stateid.dummy in
+ Exninfo.raise ~info e
+ in
if is_debug ast then
- user_error "Debug mode not available in the IDE";
+ user_error "Debug mode not available in the IDE"
+
+let ide_cmd_warns ~id {CAst.loc;v=ast} =
+ let warn msg = Feedback.(feedback ~id (Message (Warning, loc, strbrk msg))) in
if is_known_option ast then
warn "Set this option from the IDE menu instead";
if is_navigation_vernac ast || is_undo ast then
@@ -83,11 +91,15 @@ let set_doc doc = ide_doc := Some doc
let add ((s,eid),(sid,verbose)) =
let doc = get_doc () in
let pa = Pcoq.Parsable.make (Stream.of_string s) in
- let loc_ast = Stm.parse_sentence ~doc sid pa in
+ match Stm.parse_sentence ~doc sid ~entry:Pvernac.main_entry pa with
+ | None -> assert false (* s is not an empty string *)
+ | Some (loc, ast) ->
+ let loc_ast = CAst.make ~loc ast in
+ ide_cmd_checks ~last_valid:sid loc_ast;
let doc, newid, rc = Stm.add ~doc ~ontop:sid verbose loc_ast in
set_doc doc;
let rc = match rc with `NewTip -> CSig.Inl () | `Unfocus id -> CSig.Inr id in
- ide_cmd_checks ~id:newid loc_ast;
+ ide_cmd_warns ~id:newid loc_ast;
(* TODO: the "" parameter is a leftover of the times the protocol
* used to include stderr/stdout output.
*
@@ -121,10 +133,10 @@ let query (route, (s,id)) =
let annotate phrase =
let doc = get_doc () in
- let {CAst.loc;v=ast} =
- let pa = Pcoq.Parsable.make (Stream.of_string phrase) in
- Stm.parse_sentence ~doc (Stm.get_current_state ~doc) pa
- in
+ let pa = Pcoq.Parsable.make (Stream.of_string phrase) in
+ match Stm.parse_sentence ~doc (Stm.get_current_state ~doc) ~entry:Pvernac.main_entry pa with
+ | None -> Richpp.richpp_of_pp 78 (Pp.mt ())
+ | Some (_, ast) ->
(* XXX: Width should be a parameter of annotate... *)
Richpp.richpp_of_pp 78 (Ppvernac.pr_vernac ast)
@@ -534,5 +546,5 @@ let islave_init ~opts extra_args =
let () =
let open Coqtop in
- let custom = { init = islave_init; run = loop; opts = Coqargs.default_opts } in
+ let custom = { init = islave_init; run = loop; opts = Coqargs.default } in
start_coq custom
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 444ac5ab6d..8e49800982 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -625,8 +625,13 @@ let explicitize inctx impl (cf,f) args =
CApp ((ip,f),args1@args2)
| None ->
let args = exprec 1 (args,impl) in
- if List.is_empty args then f.CAst.v else CApp ((None, f), args)
- in
+ if List.is_empty args then f.CAst.v else
+ match f.CAst.v with
+ | CApp (g,args') ->
+ (* may happen with notations for a prefix of an n-ary
+ application *)
+ CApp (g,args'@args)
+ | _ -> CApp ((None, f), args) in
try expl ()
with Expl ->
let f',us = match f with { CAst.v = CRef (f,us) } -> f,us | _ -> assert false in
@@ -962,6 +967,8 @@ let rec extern inctx (custom,scopes as allscopes) vars r =
| GCast (c, c') ->
CCast (sub_extern true scopes vars c,
map_cast_type (extern_typ scopes vars) c')
+ | GInt i ->
+ CPrim(Numeral (Uint63.to_string i,true))
in insert_coercion coercion (CAst.make ?loc c)
@@ -1307,6 +1314,7 @@ let rec glob_of_pat avoid env sigma pat = DAst.make @@ match pat with
Array.map (fun (_,_,ty) -> ty) v,
Array.map (fun (_,bd,_) -> bd) v)
| PSort s -> GSort s
+ | PInt i -> GInt i
let extern_constr_pattern env sigma pat =
extern true (InConstrEntrySomeLevel,(None,[])) Id.Set.empty (glob_of_pat Id.Set.empty env sigma pat)
diff --git a/interp/declare.ml b/interp/declare.ml
index 6778fa1e7a..ea6ed8321d 100644
--- a/interp/declare.ml
+++ b/interp/declare.ml
@@ -442,6 +442,9 @@ let assumption_message id =
discussion on coqdev: "Chapter 4 of the Reference Manual", 8/10/2015) *)
Flags.if_verbose Feedback.msg_info (Id.print id ++ str " is declared")
+let register_message id =
+ Flags.if_verbose Feedback.msg_info (Id.print id ++ str " is registered")
+
(** Monomorphic universes need to survive sections. *)
let input_universe_context : Univ.ContextSet.t -> Libobject.obj =
diff --git a/interp/declare.mli b/interp/declare.mli
index 468e056909..669657af6f 100644
--- a/interp/declare.mli
+++ b/interp/declare.mli
@@ -74,6 +74,7 @@ val declare_mind : mutual_inductive_entry -> Libobject.object_name * bool
val definition_message : Id.t -> unit
val assumption_message : Id.t -> unit
+val register_message : Id.t -> unit
val fixpoint_message : int array option -> Id.t list -> unit
val cofixpoint_message : Id.t list -> unit
val recursive_message : bool (** true = fixpoint *) ->
diff --git a/interp/dumpglob.ml b/interp/dumpglob.ml
index f5be0ddbae..a537b4848c 100644
--- a/interp/dumpglob.ml
+++ b/interp/dumpglob.ml
@@ -101,6 +101,7 @@ let type_of_logical_kind = function
| Property
| Proposition
| Corollary -> "thm")
+ | IsPrimitive -> "prim"
let type_of_global_ref gr =
if Typeclasses.is_class gr then
diff --git a/interp/impargs.ml b/interp/impargs.ml
index 8a89bcdf26..959455dfd2 100644
--- a/interp/impargs.ml
+++ b/interp/impargs.ml
@@ -225,7 +225,7 @@ let rec is_rigid_head sigma t = match kind sigma t with
| Fix ((fi,i),_) -> is_rigid_head sigma (args.(fi.(i)))
| _ -> is_rigid_head sigma f)
| Lambda _ | LetIn _ | Construct _ | CoFix _ | Fix _
- | Prod _ | Meta _ | Cast _ -> assert false
+ | Prod _ | Meta _ | Cast _ | Int _ -> assert false
let is_rigid env sigma t =
let open Context.Rel.Declaration in
diff --git a/interp/notation.ml b/interp/notation.ml
index ca27d439fb..bc68d97bb8 100644
--- a/interp/notation.ml
+++ b/interp/notation.ml
@@ -574,6 +574,7 @@ type target_kind =
| Int of int_ty (* Coq.Init.Decimal.int + uint *)
| UInt of Names.inductive (* Coq.Init.Decimal.uint *)
| Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *)
+ | Int63 (* Coq.Numbers.Cyclic.Int63.Int63.int *)
type string_target_kind =
| ListByte
@@ -637,6 +638,7 @@ let rec constr_of_glob env sigma g = match DAst.get g with
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)
+ | Glob_term.GInt i -> sigma, mkInt i
| _ ->
raise NotAValidPrimToken
@@ -649,6 +651,7 @@ let rec glob_of_constr token_kind ?loc env sigma c = match Constr.kind c with
| Const (c, _) -> DAst.make ?loc (Glob_term.GRef (ConstRef c, None))
| Ind (ind, _) -> DAst.make ?loc (Glob_term.GRef (IndRef ind, None))
| Var id -> DAst.make ?loc (Glob_term.GRef (VarRef id, None))
+ | Int i -> DAst.make ?loc (Glob_term.GInt i)
| _ -> Loc.raise ?loc (PrimTokenNotationError(token_kind,env,sigma,UnexpectedTerm c))
let no_such_prim_token uninterpreted_token_kind ?loc ty =
@@ -683,6 +686,16 @@ let uninterp to_raw o (Glob_term.AnyGlobConstr n) =
end
+(** Conversion from bigint to int63 *)
+let rec int63_of_pos_bigint i =
+ let open Bigint in
+ if equal i zero then Uint63.of_int 0
+ else
+ let (quo,rem) = div2_with_rest i in
+ if rem then Uint63.add (Uint63.of_int 1)
+ (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 *)
open PrimTokenNotation
@@ -838,6 +851,32 @@ let bigint_of_z z = match Constr.kind z with
end
| _ -> raise NotAValidPrimToken
+(** Now, [Int63] from/to bigint *)
+
+let int63_of_pos_bigint ?loc n =
+ let i = int63_of_pos_bigint n in
+ mkInt i
+
+let error_negative ?loc =
+ CErrors.user_err ?loc ~hdr:"interp_int63" (Pp.str "int63 are only non-negative numbers.")
+
+let error_overflow ?loc n =
+ CErrors.user_err ?loc ~hdr:"interp_int63" Pp.(str "overflow in int63 literal: " ++ str (Bigint.to_string n))
+
+let interp_int63 ?loc n =
+ let open Bigint in
+ if is_pos_or_zero n
+ then
+ if less_than n (pow two 63)
+ then int63_of_pos_bigint ?loc n
+ else error_overflow ?loc n
+ else error_negative ?loc
+
+let bigint_of_int63 c =
+ match Constr.kind c with
+ | Int i -> Bigint.of_string (Uint63.to_string i)
+ | _ -> raise NotAValidPrimToken
+
let big2raw n =
if Bigint.is_pos_or_zero n then (Bigint.to_string n, true)
else (Bigint.to_string (Bigint.neg n), false)
@@ -856,6 +895,7 @@ let interp o ?loc n =
| UInt uint_ty when snd n -> coquint_of_rawnum uint_ty (fst n)
| UInt _ (* n <= 0 *) -> no_such_prim_token "number" ?loc o.ty_name
| Z z_pos_ty -> z_of_bigint z_pos_ty (raw2big n)
+ | Int63 -> interp_int63 ?loc (raw2big n)
in
let env = Global.env () in
let sigma = Evd.from_env env in
@@ -877,6 +917,7 @@ let uninterp o n =
| (Int _, c) -> rawnum_of_coqint c
| (UInt _, c) -> (rawnum_of_coquint c, true)
| (Z _, c) -> big2raw (bigint_of_z c)
+ | (Int63, c) -> big2raw (bigint_of_int63 c)
end o n
end
diff --git a/interp/notation.mli b/interp/notation.mli
index a482e00e81..5dcc96dc29 100644
--- a/interp/notation.mli
+++ b/interp/notation.mli
@@ -127,6 +127,7 @@ type target_kind =
| Int of int_ty (* Coq.Init.Decimal.int + uint *)
| UInt of Names.inductive (* Coq.Init.Decimal.uint *)
| Z of z_pos_ty (* Coq.Numbers.BinNums.Z and positive *)
+ | Int63 (* Coq.Numbers.Cyclic.Int63.Int63.int *)
type string_target_kind =
| ListByte
@@ -320,3 +321,6 @@ val entry_has_ident : notation_entry_level -> bool
(** Rem: printing rules for primitive token are canonical *)
val with_notation_protection : ('a -> 'b) -> 'a -> 'b
+
+(** Conversion from bigint to int63 *)
+val int63_of_pos_bigint : Bigint.bigint -> Uint63.t
diff --git a/interp/notation_ops.ml b/interp/notation_ops.ml
index 8d225fe683..890c24e633 100644
--- a/interp/notation_ops.ml
+++ b/interp/notation_ops.ml
@@ -89,9 +89,11 @@ let rec eq_notation_constr (vars1,vars2 as vars) t1 t2 = match t1, t2 with
glob_sort_eq s1 s2
| NCast (t1, c1), NCast (t2, c2) ->
(eq_notation_constr vars) t1 t2 && cast_type_eq (eq_notation_constr vars) c1 c2
+| NInt i1, NInt i2 ->
+ Uint63.equal i1 i2
| (NRef _ | NVar _ | NApp _ | NHole _ | NList _ | NLambda _ | NProd _
| NBinderList _ | NLetIn _ | NCases _ | NLetTuple _ | NIf _
- | NRec _ | NSort _ | NCast _ ), _ -> false
+ | NRec _ | NSort _ | NCast _ | NInt _), _ -> false
(**********************************************************************)
(* Re-interpret a notation as a glob_constr, taking care of binders *)
@@ -220,6 +222,7 @@ let glob_constr_of_notation_constr_with_binders ?loc g f e nc =
| NSort x -> GSort x
| NHole (x, naming, arg) -> GHole (x, naming, arg)
| NRef x -> GRef (x,None)
+ | NInt i -> GInt i
let glob_constr_of_notation_constr ?loc x =
let rec aux () x =
@@ -435,6 +438,7 @@ let notation_constr_and_vars_of_glob_constr recvars a =
NRec (fk,idl,dll,Array.map aux tl,Array.map aux bl)
| GCast (c,k) -> NCast (aux c,map_cast_type aux k)
| GSort s -> NSort s
+ | GInt i -> NInt i
| GHole (w,naming,arg) ->
if arg != None then has_ltac := true;
NHole (w, naming, arg)
@@ -623,6 +627,7 @@ let rec subst_notation_constr subst bound raw =
NRec (fk,idl,dll',tl',bl')
| NSort _ -> raw
+ | NInt _ -> raw
| NHole (knd, naming, solve) ->
let nknd = match knd with
@@ -1189,6 +1194,7 @@ let rec match_ inner u alp metas sigma a1 a2 =
match_cast (match_in u alp metas) (match_in u alp metas sigma t1 t2) c1 c2
| GSort (GType _), NSort (GType _) when not u -> sigma
| GSort s1, NSort s2 when glob_sort_eq s1 s2 -> sigma
+ | GInt i1, NInt i2 when Uint63.equal i1 i2 -> sigma
| GPatVar _, NHole _ -> (*Don't hide Metas, they bind in ltac*) raise No_match
| a, NHole _ -> sigma
@@ -1216,7 +1222,7 @@ let rec match_ inner u alp metas sigma a1 a2 =
| (GRef _ | GVar _ | GEvar _ | GPatVar _ | GApp _ | GLambda _ | GProd _
| GLetIn _ | GCases _ | GLetTuple _ | GIf _ | GRec _ | GSort _ | GHole _
- | GCast _ ), _ -> raise No_match
+ | GCast _ | GInt _ ), _ -> raise No_match
and match_in u = match_ true u
diff --git a/interp/notation_term.ml b/interp/notation_term.ml
index 0ef1f267f6..6fe20486dc 100644
--- a/interp/notation_term.ml
+++ b/interp/notation_term.ml
@@ -43,6 +43,7 @@ type notation_constr =
notation_constr array * notation_constr array
| NSort of glob_sort
| NCast of notation_constr * notation_constr cast_type
+ | NInt of Uint63.t
(** Note concerning NList: first constr is iterator, second is terminator;
first id is where each argument of the list has to be substituted
diff --git a/kernel/byterun/coq_fix_code.c b/kernel/byterun/coq_fix_code.c
index be2b05da8d..0865487c98 100644
--- a/kernel/byterun/coq_fix_code.c
+++ b/kernel/byterun/coq_fix_code.c
@@ -36,20 +36,15 @@ void init_arity () {
arity[PUSHACC6]=arity[PUSHACC7]=arity[ENVACC1]=arity[ENVACC2]=
arity[ENVACC3]=arity[ENVACC4]=arity[PUSHENVACC1]=arity[PUSHENVACC2]=
arity[PUSHENVACC3]=arity[PUSHENVACC4]=arity[APPLY1]=arity[APPLY2]=
- arity[APPLY3]=arity[RESTART]=arity[OFFSETCLOSUREM2]=
+ arity[APPLY3]=arity[APPLY4]=arity[RESTART]=arity[OFFSETCLOSUREM2]=
arity[OFFSETCLOSURE0]=arity[OFFSETCLOSURE2]=arity[PUSHOFFSETCLOSUREM2]=
arity[PUSHOFFSETCLOSURE0]=arity[PUSHOFFSETCLOSURE2]=
arity[GETFIELD0]=arity[GETFIELD1]=arity[SETFIELD0]=arity[SETFIELD1]=
arity[CONST0]=arity[CONST1]=arity[CONST2]=arity[CONST3]=
arity[PUSHCONST0]=arity[PUSHCONST1]=arity[PUSHCONST2]=arity[PUSHCONST3]=
arity[ACCUMULATE]=arity[STOP]=arity[MAKEPROD]=
- arity[ADDINT31]=arity[ADDCINT31]=arity[ADDCARRYCINT31]=
- arity[SUBINT31]=arity[SUBCINT31]=arity[SUBCARRYCINT31]=
- arity[MULCINT31]=arity[MULINT31]=arity[COMPAREINT31]=
- arity[DIV21INT31]=arity[DIVINT31]=arity[ADDMULDIVINT31]=
- arity[HEAD0INT31]=arity[TAIL0INT31]=
- arity[COMPINT31]=arity[DECOMPINT31]=
- arity[ORINT31]=arity[ANDINT31]=arity[XORINT31]=0;
+ arity[ADDINT63]=arity[SUBINT63]=arity[LTINT63]=arity[LEINT63]=
+ arity[ISINT]=arity[AREINT2]=0;
/* instruction with one operand */
arity[ACC]=arity[PUSHACC]=arity[POP]=arity[ENVACC]=arity[PUSHENVACC]=
arity[PUSH_RETADDR]=arity[APPLY]=arity[APPTERM1]=arity[APPTERM2]=
@@ -58,10 +53,20 @@ void init_arity () {
arity[MAKEBLOCK1]=arity[MAKEBLOCK2]=arity[MAKEBLOCK3]=arity[MAKEBLOCK4]=
arity[MAKEACCU]=arity[CONSTINT]=arity[PUSHCONSTINT]=arity[GRABREC]=
arity[PUSHFIELDS]=arity[GETFIELD]=arity[SETFIELD]=
- arity[BRANCH]=arity[ISCONST]=arity[ENSURESTACKCAPACITY]=1;
+ arity[BRANCH]=arity[ENSURESTACKCAPACITY]=
+ arity[CHECKADDINT63]=arity[CHECKADDCINT63]=arity[CHECKADDCARRYCINT63]=
+ arity[CHECKSUBINT63]=arity[CHECKSUBCINT63]=arity[CHECKSUBCARRYCINT63]=
+ arity[CHECKMULINT63]=arity[CHECKMULCINT63]=
+ arity[CHECKDIVINT63]=arity[CHECKMODINT63]=arity[CHECKDIVEUCLINT63]=
+ arity[CHECKDIV21INT63]=
+ arity[CHECKLXORINT63]=arity[CHECKLORINT63]=arity[CHECKLANDINT63]=
+ arity[CHECKLSLINT63]=arity[CHECKLSRINT63]=arity[CHECKADDMULDIVINT63]=
+ arity[CHECKLSLINT63CONST1]=arity[CHECKLSRINT63CONST1]=
+ arity[CHECKEQINT63]=arity[CHECKLTINT63]=arity[CHECKLEINT63]=
+ arity[CHECKCOMPAREINT63]=arity[CHECKHEAD0INT63]=arity[CHECKTAIL0INT63]=1;
/* instruction with two operands */
arity[APPTERM]=arity[MAKEBLOCK]=arity[CLOSURE]=
- arity[ARECONST]=arity[PROJ]=2;
+ arity[PROJ]=2;
/* instruction with four operands */
arity[MAKESWITCHBLOCK]=4;
/* instruction with arbitrary operands */
diff --git a/kernel/byterun/coq_fix_code.h b/kernel/byterun/coq_fix_code.h
index 638d6b5ab5..5a233e6178 100644
--- a/kernel/byterun/coq_fix_code.h
+++ b/kernel/byterun/coq_fix_code.h
@@ -29,6 +29,7 @@ void init_arity();
value coq_tcode_of_code(value code);
value coq_makeaccu (value i);
value coq_pushpop (value i);
+value coq_accucond (value i);
value coq_is_accumulate_code(value code);
#endif /* _COQ_FIX_CODE_ */
diff --git a/kernel/byterun/coq_instruct.h b/kernel/byterun/coq_instruct.h
index d92e85fdf8..c7abedaed6 100644
--- a/kernel/byterun/coq_instruct.h
+++ b/kernel/byterun/coq_instruct.h
@@ -26,7 +26,7 @@ enum instructions {
ENVACC1, ENVACC2, ENVACC3, ENVACC4, ENVACC,
PUSHENVACC1, PUSHENVACC2, PUSHENVACC3, PUSHENVACC4, PUSHENVACC,
PUSH_RETADDR,
- APPLY, APPLY1, APPLY2, APPLY3,
+ APPLY, APPLY1, APPLY2, APPLY3, APPLY4,
APPTERM, APPTERM1, APPTERM2, APPTERM3,
RETURN, RESTART, GRAB, GRABREC,
CLOSURE, CLOSUREREC, CLOSURECOFIX,
@@ -46,15 +46,21 @@ enum instructions {
MAKESWITCHBLOCK, MAKEACCU, MAKEPROD,
/* spiwack: */
BRANCH,
- ADDINT31, ADDCINT31, ADDCARRYCINT31,
- SUBINT31, SUBCINT31, SUBCARRYCINT31,
- MULCINT31, MULINT31, DIV21INT31, DIVINT31,
- ADDMULDIVINT31, COMPAREINT31,
- HEAD0INT31, TAIL0INT31,
- ISCONST, ARECONST,
- COMPINT31, DECOMPINT31,
- ORINT31, ANDINT31, XORINT31,
-/* /spiwack */
+ CHECKADDINT63, ADDINT63, CHECKADDCINT63, CHECKADDCARRYCINT63,
+ CHECKSUBINT63, SUBINT63, CHECKSUBCINT63, CHECKSUBCARRYCINT63,
+ CHECKMULINT63, CHECKMULCINT63,
+ CHECKDIVINT63, CHECKMODINT63, CHECKDIVEUCLINT63, CHECKDIV21INT63,
+ CHECKLXORINT63, CHECKLORINT63, CHECKLANDINT63,
+ CHECKLSLINT63, CHECKLSRINT63, CHECKADDMULDIVINT63,
+ CHECKLSLINT63CONST1, CHECKLSRINT63CONST1,
+
+ CHECKEQINT63, CHECKLTINT63, LTINT63, CHECKLEINT63, LEINT63,
+ CHECKCOMPAREINT63,
+
+ CHECKHEAD0INT63, CHECKTAIL0INT63,
+
+ ISINT, AREINT2,
+
STOP
};
diff --git a/kernel/byterun/coq_interp.c b/kernel/byterun/coq_interp.c
index a944dbb06c..d2c88bffcc 100644
--- a/kernel/byterun/coq_interp.c
+++ b/kernel/byterun/coq_interp.c
@@ -23,6 +23,12 @@
#include "coq_memory.h"
#include "coq_values.h"
+#ifdef ARCH_SIXTYFOUR
+#include "coq_uint63_native.h"
+#else
+#include "coq_uint63_emul.h"
+#endif
+
/* spiwack: I append here a few macros for value/number manipulation */
#define uint32_of_value(val) (((uint32_t)(val)) >> 1)
#define value_of_uint32(i) ((value)((((uint32_t)(i)) << 1) | 1))
@@ -155,6 +161,38 @@ if (sp - num_args < coq_stack_threshold) { \
#endif
#endif
+#define CheckInt1() do{ \
+ if (Is_uint63(accu)) pc++; \
+ else{ \
+ *--sp=accu; \
+ accu = Field(coq_global_data, *pc++); \
+ goto apply1; \
+ } \
+ }while(0)
+
+#define CheckInt2() do{ \
+ if (Is_uint63(accu) && Is_uint63(sp[0])) pc++; \
+ else{ \
+ *--sp=accu; \
+ accu = Field(coq_global_data, *pc++); \
+ goto apply2; \
+ } \
+ }while(0)
+
+
+
+#define CheckInt3() do{ \
+ if (Is_uint63(accu) && Is_uint63(sp[0]) && Is_uint63(sp[1]) ) pc++; \
+ else{ \
+ *--sp=accu; \
+ accu = Field(coq_global_data, *pc++); \
+ goto apply3; \
+ } \
+ }while(0)
+
+#define AllocCarry(cond) Alloc_small(accu, 1, (cond)? coq_tag_C1 : coq_tag_C0)
+#define AllocPair() Alloc_small(accu, 2, coq_tag_pair)
+
/* For signal handling, we hijack some code from the caml runtime */
extern intnat caml_signals_are_pending;
@@ -372,8 +410,10 @@ value coq_interprete
goto check_stack;
}
Instruct(APPLY1) {
- value arg1 = sp[0];
+ value arg1;
+ apply1:
print_instr("APPLY1");
+ arg1 = sp[0];
sp -= 3;
sp[0] = arg1;
sp[1] = (value)pc;
@@ -388,10 +428,14 @@ value coq_interprete
coq_extra_args = 0;
goto check_stack;
}
+
Instruct(APPLY2) {
- value arg1 = sp[0];
- value arg2 = sp[1];
+ value arg1;
+ value arg2;
+ apply2:
print_instr("APPLY2");
+ arg1 = sp[0];
+ arg2 = sp[1];
sp -= 3;
sp[0] = arg1;
sp[1] = arg2;
@@ -403,11 +447,16 @@ value coq_interprete
coq_extra_args = 1;
goto check_stack;
}
+
Instruct(APPLY3) {
- value arg1 = sp[0];
- value arg2 = sp[1];
- value arg3 = sp[2];
+ value arg1;
+ value arg2;
+ value arg3;
+ apply3:
print_instr("APPLY3");
+ arg1 = sp[0];
+ arg2 = sp[1];
+ arg3 = sp[2];
sp -= 3;
sp[0] = arg1;
sp[1] = arg2;
@@ -420,7 +469,28 @@ value coq_interprete
coq_extra_args = 2;
goto check_stack;
}
- /* Stack checks */
+
+ Instruct(APPLY4) {
+ value arg1 = sp[0];
+ value arg2 = sp[1];
+ value arg3 = sp[2];
+ value arg4 = sp[3];
+ print_instr("APPLY4");
+ sp -= 3;
+ sp[0] = arg1;
+ sp[1] = arg2;
+ sp[2] = arg3;
+ sp[3] = arg4;
+ sp[4] = (value)pc;
+ sp[5] = coq_env;
+ sp[6] = Val_long(coq_extra_args);
+ pc = Code_val(accu);
+ coq_env = accu;
+ coq_extra_args = 3;
+ goto check_stack;
+ }
+
+ /* Stack checks */
check_stack:
print_instr("check_stack");
@@ -1127,7 +1197,6 @@ value coq_interprete
Next;
}
- /* spiwack: code for interpreting compiled integers */
Instruct(BRANCH) {
/* unconditional branching */
print_instr("BRANCH");
@@ -1136,338 +1205,339 @@ value coq_interprete
Next;
}
- Instruct(ADDINT31) {
+ Instruct(CHECKADDINT63){
+ print_instr("CHECKADDINT63");
+ CheckInt2();
+ }
+ Instruct(ADDINT63) {
/* Adds the integer in the accumulator with
the one ontop of the stack (which is poped)*/
- print_instr("ADDINT31");
- accu =
- (value)((uint32_t) accu + (uint32_t) *sp++ - 1);
- /* nota,unlike CaML we don't want
- to have a different behavior depending on the
- architecture. Thus we cast the operand to uint32 */
+ print_instr("ADDINT63");
+ accu = uint63_add(accu, *sp++);
Next;
}
- Instruct (ADDCINT31) {
- print_instr("ADDCINT31");
+ Instruct (CHECKADDCINT63) {
+ print_instr("CHECKADDCINT63");
+ CheckInt2();
/* returns the sum with a carry */
- uint32_t s;
- s = (uint32_t)accu + (uint32_t)*sp++ - 1;
- if( (uint32_t)s < (uint32_t)accu ) {
- /* carry */
- Alloc_small(accu, 1, 2); /* ( _ , arity, tag ) */
- }
- else {
- /*no carry */
- Alloc_small(accu, 1, 1);
- }
- Field(accu, 0)=(value)s;
+ value s;
+ s = uint63_add(accu, *sp++);
+ AllocCarry(uint63_lt(s,accu));
+ Field(accu, 0) = s;
Next;
}
- Instruct (ADDCARRYCINT31) {
- print_instr("ADDCARRYCINT31");
+ Instruct (CHECKADDCARRYCINT63) {
+ print_instr("ADDCARRYCINT63");
+ CheckInt2();
/* returns the sum plus one with a carry */
- uint32_t s;
- s = (uint32_t)accu + (uint32_t)*sp++ + 1;
- if( (uint32_t)s <= (uint32_t)accu ) {
- /* carry */
- Alloc_small(accu, 1, 2); /* ( _ , arity, tag ) */
- }
- else {
- /*no carry */
- Alloc_small(accu, 1, 1);
- }
- Field(accu, 0)=(value)s;
+ value s;
+ s = uint63_addcarry(accu, *sp++);
+ AllocCarry(uint63_leq(s, accu));
+ Field(accu, 0) = s;
Next;
}
- Instruct (SUBINT31) {
- print_instr("SUBINT31");
+ Instruct (CHECKSUBINT63) {
+ print_instr("CHECKSUBINT63");
+ CheckInt2();
+ }
+ Instruct (SUBINT63) {
+ print_instr("SUBINT63");
/* returns the subtraction */
- accu =
- (value)((uint32_t) accu - (uint32_t) *sp++ + 1);
+ accu = uint63_sub(accu, *sp++);
Next;
}
- Instruct (SUBCINT31) {
- print_instr("SUBCINT31");
+ Instruct (CHECKSUBCINT63) {
+ print_instr("SUBCINT63");
+ CheckInt2();
/* returns the subtraction with a carry */
- uint32_t b;
- uint32_t s;
- b = (uint32_t)*sp++;
- s = (uint32_t)accu - b + 1;
- if( (uint32_t)accu < b ) {
- /* carry */
- Alloc_small(accu, 1, 2); /* ( _ , arity, tag ) */
- }
- else {
- /*no carry */
- Alloc_small(accu, 1, 1);
- }
- Field(accu, 0)=(value)s;
+ value b;
+ value s;
+ b = *sp++;
+ s = uint63_sub(accu,b);
+ AllocCarry(uint63_lt(accu,b));
+ Field(accu, 0) = s;
Next;
}
- Instruct (SUBCARRYCINT31) {
- print_instr("SUBCARRYCINT31");
+ Instruct (CHECKSUBCARRYCINT63) {
+ print_instr("SUBCARRYCINT63");
+ CheckInt2();
/* returns the subtraction minus one with a carry */
- uint32_t b;
- uint32_t s;
- b = (uint32_t)*sp++;
- s = (value)((uint32_t)accu - b - 1);
- if( (uint32_t)accu <= b ) {
- /* carry */
- Alloc_small(accu, 1, 2); /* ( _ , arity, tag ) */
- }
- else {
- /*no carry */
- Alloc_small(accu, 1, 1);
- }
- Field(accu, 0)=(value)s;
+ value b;
+ value s;
+ b = *sp++;
+ s = uint63_subcarry(accu,b);
+ AllocCarry(uint63_leq(accu,b));
+ Field(accu, 0) = s;
Next;
}
- Instruct (MULINT31) {
+ Instruct (CHECKMULINT63) {
+ print_instr("MULINT63");
+ CheckInt2();
/* returns the multiplication */
- print_instr("MULINT31");
- accu =
- value_of_uint32((uint32_of_value(accu)) * (uint32_of_value(*sp++)));
+ accu = uint63_mul(accu,*sp++);
Next;
}
- Instruct (MULCINT31) {
- /*returns the multiplication on a double size word
- (special case for 0) */
- print_instr("MULCINT31");
- uint64_t p;
+ Instruct (CHECKMULCINT63) {
+ /*returns the multiplication on a pair */
+ print_instr("MULCINT63");
+ CheckInt2();
/*accu = 2v+1, *sp=2w+1 ==> p = 2v*w */
- p = UI64_of_value (accu) * UI64_of_uint32 ((*sp++)^1);
- if (p == 0) {
- accu = (value)1;
+ /* TODO: implement
+ p = I64_mul (UI64_of_value (accu), UI64_of_uint32 ((*sp++)^1));
+ AllocPair(); */
+ /* Field(accu, 0) = (value)(I64_lsr(p,31)|1) ; */ /*higher part*/
+ /* Field(accu, 1) = (value)(I64_to_int32(p)|1); */ /*lower part*/
+ value x = accu;
+ AllocPair();
+ Field(accu, 1) = uint63_mulc(x, *sp++, &Field(accu, 0));
+ Next;
+ }
+
+ Instruct(CHECKDIVINT63) {
+ print_instr("CHEKDIVINT63");
+ CheckInt2();
+ /* spiwack: a priori no need of the NON_STANDARD_DIV_MOD flag
+ since it probably only concerns negative number.
+ needs to be checked at this point */
+ value divisor;
+ divisor = *sp++;
+ if (uint63_eq0(divisor)) {
+ accu = divisor;
}
else {
- /* the output type is supposed to have a constant constructor
- and a non-constant constructor (in that order), the tag
- of the non-constant constructor is then 1 */
- Alloc_small(accu, 2, 1); /* ( _ , arity, tag ) */
- /*unsigned shift*/
- Field(accu, 0) = (value)((p >> 31)|1) ; /*higher part*/
- Field(accu, 1) = (value)((uint32_t)p|1); /*lower part*/
- }
+ accu = uint63_div(accu, divisor);
+ }
Next;
}
- Instruct (DIV21INT31) {
- print_instr("DIV21INT31");
- /* spiwack: takes three int31 (the two first ones represent an
- int62) and performs the euclidian division of the
- int62 by the int31 */
- uint64_t bigint;
- bigint = UI64_of_value(accu);
- bigint = (bigint << 31) | UI64_of_value(*sp++);
- uint64_t divisor;
- divisor = UI64_of_value(*sp++);
- Alloc_small(accu, 2, 1); /* ( _ , arity, tag ) */
- if (divisor == 0) {
- Field(accu, 0) = 1; /* 2*0+1 */
- Field(accu, 1) = 1; /* 2*0+1 */
+ Instruct(CHECKMODINT63) {
+ print_instr("CHEKMODINT63");
+ CheckInt2();
+ value divisor;
+ divisor = *sp++;
+ if (uint63_eq0(divisor)) {
+ accu = divisor;
}
- else {
- uint64_t quo, mod;
- quo = bigint / divisor;
- mod = bigint % divisor;
- Field(accu, 0) = value_of_uint32((uint32_t)(quo));
- Field(accu, 1) = value_of_uint32((uint32_t)(mod));
+ else {
+ accu = uint63_mod(accu,divisor);
}
Next;
}
- Instruct (DIVINT31) {
- print_instr("DIVINT31");
+ Instruct (CHECKDIVEUCLINT63) {
+ print_instr("DIVEUCLINT63");
+ CheckInt2();
/* spiwack: a priori no need of the NON_STANDARD_DIV_MOD flag
since it probably only concerns negative number.
needs to be checked at this point */
- uint32_t divisor;
- divisor = uint32_of_value(*sp++);
- if (divisor == 0) {
+ value divisor;
+ divisor = *sp++;
+ if (uint63_eq0(divisor)) {
Alloc_small(accu, 2, 1); /* ( _ , arity, tag ) */
- Field(accu, 0) = 1; /* 2*0+1 */
- Field(accu, 1) = 1; /* 2*0+1 */
+ Field(accu, 0) = divisor;
+ Field(accu, 1) = divisor;
}
else {
- uint32_t modulus;
- modulus = uint32_of_value(accu);
+ value modulus;
+ modulus = accu;
Alloc_small(accu, 2, 1); /* ( _ , arity, tag ) */
- Field(accu, 0) = value_of_uint32(modulus/divisor);
- Field(accu, 1) = value_of_uint32(modulus%divisor);
+ Field(accu, 0) = uint63_div(modulus,divisor);
+ Field(accu, 1) = uint63_mod(modulus,divisor);
}
Next;
}
- Instruct (ADDMULDIVINT31) {
- print_instr("ADDMULDIVINT31");
- /* higher level shift (does shifts and cycles and such) */
- uint32_t shiftby;
- shiftby = uint32_of_value(accu);
- if (shiftby > 31) {
- if (shiftby < 62) {
- sp++;
- accu = (value)(((((uint32_t)*sp++)^1) << (shiftby - 31)) | 1);
- }
- else {
- sp+=2;
- accu = (value)(1);
- }
+ Instruct (CHECKDIV21INT63) {
+ print_instr("DIV21INT63");
+ CheckInt3();
+ /* spiwack: takes three int31 (the two first ones represent an
+ int62) and performs the euclidian division of the
+ int62 by the int31 */
+ /* TODO: implement this
+ bigint = UI64_of_value(accu);
+ bigint = I64_or(I64_lsl(bigint, 31),UI64_of_value(*sp++));
+ uint64 divisor;
+ divisor = UI64_of_value(*sp++);
+ Alloc_small(accu, 2, 1); */ /* ( _ , arity, tag ) */
+ /* if (I64_is_zero (divisor)) {
+ Field(accu, 0) = 1; */ /* 2*0+1 */
+ /* Field(accu, 1) = 1; */ /* 2*0+1 */
+ /* }
+ else {
+ uint64 quo, mod;
+ I64_udivmod(bigint, divisor, &quo, &mod);
+ Field(accu, 0) = value_of_uint32(I64_to_int32(quo));
+ Field(accu, 1) = value_of_uint32(I64_to_int32(mod));
+ } */
+ value bigint; /* TODO: fix */
+ bigint = *sp++; /* TODO: take accu into account */
+ value divisor;
+ divisor = *sp++;
+ if (uint63_eq0(divisor)) {
+ Alloc_small(accu, 2, 1);
+ Field(accu, 0) = divisor;
+ Field(accu, 1) = divisor;
}
- else{
- /* *sp = 2*x+1 --> accu = 2^(shiftby+1)*x */
- accu = (value)((((uint32_t)*sp++)^1) << shiftby);
- /* accu = 2^(shiftby+1)*x --> 2^(shifby+1)*x+2*y/2^(31-shiftby)+1 */
- accu = (value)((accu | (((uint32_t)(*sp++)) >> (31-shiftby)))|1);
+ else {
+ value quo, mod;
+ mod = uint63_div21(accu, bigint, divisor, &quo);
+ Alloc_small(accu, 2, 1);
+ Field(accu, 0) = quo;
+ Field(accu, 1) = mod;
}
Next;
}
- Instruct (COMPAREINT31) {
- /* returns Eq if equal, Lt if accu is less than *sp, Gt otherwise */
- /* assumes Inductive _ : _ := Eq | Lt | Gt */
- print_instr("COMPAREINT31");
- if ((uint32_t)accu == (uint32_t)*sp) {
- accu = 1; /* 2*0+1 */
- sp++;
- }
- else{if ((uint32_t)accu < (uint32_t)(*sp++)) {
- accu = 3; /* 2*1+1 */
- }
- else{
- accu = 5; /* 2*2+1 */
- }}
+ Instruct(CHECKLXORINT63) {
+ print_instr("CHECKLXORINT63");
+ CheckInt2();
+ accu = uint63_lxor(accu,*sp++);
Next;
}
-
- Instruct (HEAD0INT31) {
- int r = 0;
- uint32_t x;
- print_instr("HEAD0INT31");
- x = (uint32_t) accu;
- if (!(x & 0xFFFF0000)) { x <<= 16; r += 16; }
- if (!(x & 0xFF000000)) { x <<= 8; r += 8; }
- if (!(x & 0xF0000000)) { x <<= 4; r += 4; }
- if (!(x & 0xC0000000)) { x <<= 2; r += 2; }
- if (!(x & 0x80000000)) { x <<=1; r += 1; }
- if (!(x & 0x80000000)) { r += 1; }
- accu = value_of_uint32(r);
+
+ Instruct(CHECKLORINT63) {
+ print_instr("CHECKLORINT63");
+ CheckInt2();
+ accu = uint63_lor(accu,*sp++);
Next;
}
-
- Instruct (TAIL0INT31) {
- int r = 0;
- uint32_t x;
- print_instr("TAIL0INT31");
- x = (((uint32_t) accu >> 1) | 0x80000000);
- if (!(x & 0xFFFF)) { x >>= 16; r += 16; }
- if (!(x & 0x00FF)) { x >>= 8; r += 8; }
- if (!(x & 0x000F)) { x >>= 4; r += 4; }
- if (!(x & 0x0003)) { x >>= 2; r += 2; }
- if (!(x & 0x0001)) { x >>=1; r += 1; }
- if (!(x & 0x0001)) { r += 1; }
- accu = value_of_uint32(r);
+
+ Instruct(CHECKLANDINT63) {
+ print_instr("CHECKLANDINT63");
+ CheckInt2();
+ accu = uint63_land(accu,*sp++);
Next;
}
- Instruct (ISCONST) {
- /* Branches if the accu does not contain a constant
- (i.e., a non-block value) */
- print_instr("ISCONST");
- if ((accu & 1) == 0) /* last bit is 0 -> it is a block */
- pc += *pc;
- else
- pc++;
+ Instruct(CHECKLSLINT63) {
+ print_instr("CHECKLSLINT63");
+ CheckInt2();
+ value p = *sp++;
+ accu = uint63_lsl(accu,p);
Next;
+ }
+ Instruct(CHECKLSRINT63) {
+ print_instr("CHECKLSRINT63");
+ CheckInt2();
+ value p = *sp++;
+ accu = uint63_lsr(accu,p);
+ Next;
}
- Instruct (ARECONST) {
- /* Branches if the n first values on the stack are not
- all constansts */
- print_instr("ARECONST");
- int i, n, ok;
- ok = 1;
- n = *pc++;
- for(i=0; i < n; i++) {
- if ((sp[i] & 1) == 0) {
- ok = 0;
- break;
- }
+ Instruct(CHECKLSLINT63CONST1) {
+ print_instr("CHECKLSLINT63CONST1");
+ if (Is_uint63(accu)) {
+ pc++;
+ accu = uint63_lsl1(accu);
+ Next;
+ } else {
+ *--sp = uint63_one();
+ *--sp = accu;
+ accu = Field(coq_global_data, *pc++);
+ goto apply2;
}
- if(ok) pc++; else pc += *pc;
+ }
+
+ Instruct(CHECKLSRINT63CONST1) {
+ print_instr("CHECKLSRINT63CONST1");
+ if (Is_uint63(accu)) {
+ pc++;
+ accu = uint63_lsr1(accu);
+ Next;
+ } else {
+ *--sp = uint63_one();
+ *--sp = accu;
+ accu = Field(coq_global_data, *pc++);
+ goto apply2;
+ }
+ }
+
+ Instruct (CHECKADDMULDIVINT63) {
+ print_instr("CHECKADDMULDIVINT63");
+ CheckInt3();
+ value x;
+ value y;
+ x = *sp++;
+ y = *sp++;
+ accu = uint63_addmuldiv(accu,x,y);
Next;
}
- Instruct (COMPINT31) {
- /* makes an 31-bit integer out of the accumulator and
- the 30 first values of the stack
- and put it in the accumulator (the accumulator then the
- topmost get to be the heavier bits) */
- print_instr("COMPINT31");
- int i;
- /*accu=accu or accu = (value)((unsigned long)1-accu) if bool
- is used for the bits */
- for(i=0; i < 30; i++) {
- accu = (value) ((((uint32_t)accu-1) << 1) | *sp++);
- /* -1 removes the tag bit, << 1 multiplies the value by 2,
- | *sp++ pops the last value and add it (no carry involved)
- not that it reintroduces a tag bit */
- /* alternative, if bool is used for the bits :
- accu = (value) ((((unsigned long)accu) << 1) & !*sp++); */
+ Instruct (CHECKEQINT63) {
+ print_instr("CHECKEQINT63");
+ CheckInt2();
+ accu = uint63_eq(accu,*sp++) ? coq_true : coq_false;
+ Next;
+ }
+
+ Instruct (CHECKLTINT63) {
+ print_instr("CHECKLTINT63");
+ CheckInt2();
+ }
+ Instruct (LTINT63) {
+ print_instr("LTINT63");
+ accu = uint63_lt(accu,*sp++) ? coq_true : coq_false;
+ Next;
+ }
+
+ Instruct (CHECKLEINT63) {
+ print_instr("CHECKLEINT63");
+ CheckInt2();
+ }
+ Instruct (LEINT63) {
+ print_instr("LEINT63");
+ accu = uint63_leq(accu,*sp++) ? coq_true : coq_false;
+ Next;
+ }
+
+ Instruct (CHECKCOMPAREINT63) {
+ /* returns Eq if equal, Lt if accu is less than *sp, Gt otherwise */
+ /* assumes Inductive _ : _ := Eq | Lt | Gt */
+ print_instr("CHECKCOMPAREINT63");
+ CheckInt2();
+ if (uint63_eq(accu,*sp)) {
+ accu = coq_Eq;
+ sp++;
}
+ else accu = uint63_lt(accu,*sp++) ? coq_Lt : coq_Gt;
Next;
}
- Instruct (DECOMPINT31) {
- /* builds a block out of a 31-bit integer (from the accumulator),
- used before cases */
- int i;
- value block;
- print_instr("DECOMPINT31");
- Alloc_small(block, 31, 1); // Alloc_small(*, size, tag)
- for(i = 30; i >= 0; i--) {
- Field(block, i) = (value)(accu & 3); /* two last bits of the accumulator */
- //Field(block, i) = 3;
- accu = (value) ((uint32_t)accu >> 1) | 1; /* last bit must be a one */
- };
- accu = block;
+ Instruct (CHECKHEAD0INT63) {
+ print_instr("CHECKHEAD0INT63");
+ CheckInt1();
+ accu = uint63_head0(accu);
Next;
}
- Instruct (ORINT31) {
- /* returns the bitwise or */
- print_instr("ORINT31");
- accu =
- value_of_uint32((uint32_of_value(accu)) | (uint32_of_value(*sp++)));
- Next;
+ Instruct (CHECKTAIL0INT63) {
+ print_instr("CHECKTAIL0INT63");
+ CheckInt1();
+ accu = uint63_tail0(accu);
+ Next;
}
- Instruct (ANDINT31) {
- /* returns the bitwise and */
- print_instr("ANDINT31");
- accu =
- value_of_uint32((uint32_of_value(accu)) & (uint32_of_value(*sp++)));
+ Instruct (ISINT){
+ print_instr("ISINT");
+ accu = (Is_uint63(accu)) ? coq_true : coq_false;
Next;
}
- Instruct (XORINT31) {
- /* returns the bitwise xor */
- print_instr("XORINT31");
- accu =
- value_of_uint32((uint32_of_value(accu)) ^ (uint32_of_value(*sp++)));
+ Instruct (AREINT2){
+ print_instr("AREINT2");
+ accu = (Is_uint63(accu) && Is_uint63(sp[0])) ? coq_true : coq_false;
+ sp++;
Next;
}
- /* /spiwack */
-
-
/* Debugging and machine control */
diff --git a/kernel/byterun/coq_uint63_emul.h b/kernel/byterun/coq_uint63_emul.h
new file mode 100644
index 0000000000..5499f124a2
--- /dev/null
+++ b/kernel/byterun/coq_uint63_emul.h
@@ -0,0 +1,97 @@
+# pragma once
+
+# include <caml/callback.h>
+# include <caml/stack.h>
+
+
+#define Is_uint63(v) (Tag_val(v) == Custom_tag)
+
+# define DECLARE_NULLOP(name) \
+value uint63_##name() { \
+ static value* cb = 0; \
+ CAMLparam0(); \
+ if (!cb) cb = caml_named_value("uint63 " #name); \
+ CAMLreturn(*cb); \
+ }
+
+# define DECLARE_UNOP(name) \
+value uint63_##name(value x) { \
+ static value* cb = 0; \
+ CAMLparam1(x); \
+ if (!cb) cb = caml_named_value("uint63 " #name); \
+ CAMLreturn(caml_callback(*cb, x)); \
+ }
+
+# define DECLARE_PREDICATE(name) \
+value uint63_##name(value x) { \
+ static value* cb = 0; \
+ CAMLparam1(x); \
+ if (!cb) cb = caml_named_value("uint63 " #name); \
+ CAMLreturn(Int_val(caml_callback(*cb, x))); \
+ }
+
+# define DECLARE_BINOP(name) \
+value uint63_##name(value x, value y) { \
+ static value* cb = 0; \
+ CAMLparam2(x, y); \
+ if (!cb) cb = caml_named_value("uint63 " #name); \
+ CAMLreturn(caml_callback2(*cb, x, y)); \
+ }
+
+# define DECLARE_RELATION(name) \
+value uint63_##name(value x, value y) { \
+ static value* cb = 0; \
+ CAMLparam2(x, y); \
+ if (!cb) cb = caml_named_value("uint63 " #name); \
+ CAMLreturn(Int_val(caml_callback2(*cb, x, y))); \
+ }
+
+# define DECLARE_TEROP(name) \
+value uint63_##name(value x, value y, value z) { \
+ static value* cb = 0; \
+ CAMLparam3(x, y, z); \
+ if (!cb) cb = caml_named_value("uint63 " #name); \
+ CAMLreturn(caml_callback3(*cb, x, y, z)); \
+ }
+
+
+DECLARE_NULLOP(one)
+DECLARE_BINOP(add)
+DECLARE_BINOP(addcarry)
+DECLARE_TEROP(addmuldiv)
+DECLARE_BINOP(div)
+DECLARE_TEROP(div21_ml)
+DECLARE_RELATION(eq)
+DECLARE_PREDICATE(eq0)
+DECLARE_UNOP(head0)
+DECLARE_BINOP(land)
+DECLARE_RELATION(leq)
+DECLARE_BINOP(lor)
+DECLARE_BINOP(lsl)
+DECLARE_UNOP(lsl1)
+DECLARE_BINOP(lsr)
+DECLARE_UNOP(lsr1)
+DECLARE_RELATION(lt)
+DECLARE_BINOP(lxor)
+DECLARE_BINOP(mod)
+DECLARE_BINOP(mul)
+DECLARE_BINOP(mulc_ml)
+DECLARE_BINOP(sub)
+DECLARE_BINOP(subcarry)
+DECLARE_UNOP(tail0)
+
+value uint63_div21(value x, value y, value z, value* q) {
+ CAMLparam3(x, y, z);
+ CAMLlocal1(qr);
+ qr = uint63_div21_ml(x, y, z);
+ *q = Field(qr, 0);
+ CAMLreturn(Field(qr, 1));
+}
+
+value uint63_mulc(value x, value y, value* h) {
+ CAMLparam2(x, y);
+ CAMLlocal1(hl);
+ hl = uint63_mulc_ml(x, y);
+ *h = Field(hl, 0);
+ CAMLreturn(Field(hl, 1));
+}
diff --git a/kernel/byterun/coq_uint63_native.h b/kernel/byterun/coq_uint63_native.h
new file mode 100644
index 0000000000..92f4dc79bc
--- /dev/null
+++ b/kernel/byterun/coq_uint63_native.h
@@ -0,0 +1,125 @@
+#define Is_uint63(v) (Is_long(v))
+
+#define uint63_of_value(val) ((uint64_t)(val) >> 1)
+
+/* 2^63 * y + x as a value */
+//#define Val_intint(x,y) ((value)(((uint64_t)(x)) << 1 + ((uint64_t)(y) << 64)))
+
+#define uint63_zero ((value) 1) /* 2*0 + 1 */
+#define uint63_one() ((value) 3) /* 2*1 + 1 */
+
+#define uint63_eq(x,y) ((x) == (y))
+#define uint63_eq0(x) ((x) == (uint64_t)1)
+#define uint63_lt(x,y) ((uint64_t) (x) < (uint64_t) (y))
+#define uint63_leq(x,y) ((uint64_t) (x) <= (uint64_t) (y))
+
+#define uint63_add(x,y) ((value)((uint64_t) (x) + (uint64_t) (y) - 1))
+#define uint63_addcarry(x,y) ((value)((uint64_t) (x) + (uint64_t) (y) + 1))
+#define uint63_sub(x,y) ((value)((uint64_t) (x) - (uint64_t) (y) + 1))
+#define uint63_subcarry(x,y) ((value)((uint64_t) (x) - (uint64_t) (y) - 1))
+#define uint63_mul(x,y) (Val_long(uint63_of_value(x) * uint63_of_value(y)))
+#define uint63_div(x,y) (Val_long(uint63_of_value(x) / uint63_of_value(y)))
+#define uint63_mod(x,y) (Val_long(uint63_of_value(x) % uint63_of_value(y)))
+
+#define uint63_lxor(x,y) ((value)(((uint64_t)(x) ^ (uint64_t)(y)) | 1))
+#define uint63_lor(x,y) ((value)((uint64_t)(x) | (uint64_t)(y)))
+#define uint63_land(x,y) ((value)((uint64_t)(x) & (uint64_t)(y)))
+
+/* TODO: is + or | better? OCAML uses + */
+/* TODO: is - or ^ better? */
+#define uint63_lsl(x,y) ((y) < (uint64_t) 127 ? ((value)((((uint64_t)(x)-1) << (uint63_of_value(y))) | 1)) : uint63_zero)
+#define uint63_lsr(x,y) ((y) < (uint64_t) 127 ? ((value)(((uint64_t)(x) >> (uint63_of_value(y))) | 1)) : uint63_zero)
+#define uint63_lsl1(x) ((value)((((uint64_t)(x)-1) << 1) +1))
+#define uint63_lsr1(x) ((value)(((uint64_t)(x) >> 1) |1))
+
+/* addmuldiv(p,x,y) = x * 2^p + y / 2 ^ (63 - p) */
+/* (modulo 2^63) for p <= 63 */
+value uint63_addmuldiv(uint64_t p, uint64_t x, uint64_t y) {
+ uint64_t shiftby = uint63_of_value(p);
+ value r = (value)((uint64_t)(x^1) << shiftby);
+ r |= ((uint64_t)y >> (63-shiftby)) | 1;
+ return r;
+}
+
+value uint63_head0(uint64_t x) {
+ int r = 0;
+ if (!(x & 0xFFFFFFFF00000000)) { x <<= 32; r += 32; }
+ if (!(x & 0xFFFF000000000000)) { x <<= 16; r += 16; }
+ if (!(x & 0xFF00000000000000)) { x <<= 8; r += 8; }
+ if (!(x & 0xF000000000000000)) { x <<= 4; r += 4; }
+ if (!(x & 0xC000000000000000)) { x <<= 2; r += 2; }
+ if (!(x & 0x8000000000000000)) { x <<=1; r += 1; }
+ return Val_int(r);
+}
+
+value uint63_tail0(value x) {
+ int r = 0;
+ x = (uint64_t)x >> 1;
+ if (!(x & 0xFFFFFFFF)) { x >>= 32; r += 32; }
+ if (!(x & 0x0000FFFF)) { x >>= 16; r += 16; }
+ if (!(x & 0x000000FF)) { x >>= 8; r += 8; }
+ if (!(x & 0x0000000F)) { x >>= 4; r += 4; }
+ if (!(x & 0x00000003)) { x >>= 2; r += 2; }
+ if (!(x & 0x00000001)) { x >>=1; r += 1; }
+ return Val_int(r);
+}
+
+value uint63_mulc(value x, value y, value* h) {
+ x = (uint64_t)x >> 1;
+ y = (uint64_t)y >> 1;
+ uint64_t lx = x & 0xFFFFFFFF;
+ uint64_t ly = y & 0xFFFFFFFF;
+ uint64_t hx = x >> 32;
+ uint64_t hy = y >> 32;
+ uint64_t hr = hx * hy;
+ uint64_t lr = lx * ly;
+ lx *= hy;
+ ly *= hx;
+ hr += (lx >> 32) + (ly >> 32);
+ lx <<= 32;
+ lr += lx;
+ if (lr < lx) { hr++; }
+ ly <<= 32;
+ lr += ly;
+ if (lr < ly) { hr++; }
+ hr = (hr << 1) | (lr >> 63);
+ *h = Val_int(hr);
+ return Val_int(lr);
+}
+
+#define lt128(xh,xl,yh,yl) (uint63_lt(xh,yh) || (uint63_eq(xh,yh) && uint63_lt(xl,yl)))
+#define le128(xh,xl,yh,yl) (uint63_lt(xh,yh) || (uint63_eq(xh,yh) && uint63_leq(xl,yl)))
+
+value uint63_div21(value xh, value xl, value y, value* q) {
+ xh = (uint64_t)xh >> 1;
+ xl = ((uint64_t)xl >> 1) | ((uint64_t)xh << 63);
+ xh = (uint64_t)xh >> 1;
+ uint64_t maskh = 0;
+ uint64_t maskl = 1;
+ uint64_t dh = 0;
+ uint64_t dl = (uint64_t)y >> 1;
+ int cmp = 1;
+ while (dh >= 0 && cmp) {
+ cmp = lt128(dh,dl,xh,xl);
+ dh = (dh << 1) | (dl >> 63);
+ dl = dl << 1;
+ maskh = (maskh << 1) | (maskl >> 63);
+ maskl = maskl << 1;
+ }
+ uint64_t remh = xh;
+ uint64_t reml = xl;
+ uint64_t quotient = 0;
+ while (maskh | maskl) {
+ if (le128(dh,dl,remh,reml)) {
+ quotient = quotient | maskl;
+ if (uint63_lt(reml,dl)) {remh = remh - dh - 1;} else {remh = remh - dh;}
+ reml = reml - dl;
+ }
+ maskl = (maskl >> 1) | (maskh << 63);
+ maskh = maskh >> 1;
+ dl = (dl >> 1) | (dh << 63);
+ dh = dh >> 1;
+ }
+ *q = Val_int(quotient);
+ return Val_int(reml);
+}
diff --git a/kernel/byterun/coq_values.h b/kernel/byterun/coq_values.h
index bb0f0eb5e4..0cf6ccf532 100644
--- a/kernel/byterun/coq_values.h
+++ b/kernel/byterun/coq_values.h
@@ -28,6 +28,16 @@
/* Les blocs accumulate */
#define Is_accu(v) (Is_block(v) && (Tag_val(v) == Accu_tag))
-
#define IS_EVALUATED_COFIX(v) (Is_accu(v) && Is_block(Field(v,1)) && (Tag_val(Field(v,1)) == ATOM_COFIXEVALUATED_TAG))
+
+/* */
+#define coq_tag_C1 2
+#define coq_tag_C0 1
+#define coq_tag_pair 1
+#define coq_true Val_int(0)
+#define coq_false Val_int(1)
+#define coq_Eq Val_int(0)
+#define coq_Lt Val_int(1)
+#define coq_Gt Val_int(2)
+
#endif /* _COQ_VALUES_ */
diff --git a/kernel/byterun/dune b/kernel/byterun/dune
index 3a714a8a59..c3c44670be 100644
--- a/kernel/byterun/dune
+++ b/kernel/byterun/dune
@@ -6,5 +6,5 @@
(rule
(targets coq_jumptbl.h)
- (deps (:h-file coq_instruct.h))
- (action (run ./make_jumptbl.sh %{h-file} %{targets})))
+ (deps (:h-file coq_instruct.h) make_jumptbl.sh)
+ (action (bash "./make_jumptbl.sh %{h-file} %{targets}")))
diff --git a/kernel/cClosure.ml b/kernel/cClosure.ml
index 196bb16f32..5fec55fea1 100644
--- a/kernel/cClosure.ml
+++ b/kernel/cClosure.ml
@@ -28,8 +28,9 @@ open Util
open Pp
open Names
open Constr
-open Vars
+open Declarations
open Environ
+open Vars
open Esubst
let stats = ref false
@@ -303,6 +304,7 @@ and fterm =
| FProd of Name.t * fconstr * constr * fconstr subs
| FLetIn of Name.t * fconstr * fconstr * constr * fconstr subs
| FEvar of existential * fconstr subs
+ | FInt of Uint63.t
| FLIFT of int * fconstr
| FCLOS of constr * fconstr subs
| FLOCKED
@@ -335,19 +337,22 @@ type clos_infos = {
i_flags : reds;
i_cache : infos_cache }
-type clos_tab = fconstr KeyTable.t
+type clos_tab = fconstr constant_def KeyTable.t
let info_flags info = info.i_flags
let info_env info = info.i_cache.i_env
(**********************************************************************)
(* The type of (machine) stacks (= lambda-bar-calculus' contexts) *)
+type 'a next_native_args = (CPrimitives.arg_kind * 'a) list
type stack_member =
| Zapp of fconstr array
| ZcaseT of case_info * constr * constr array * fconstr subs
| Zproj of Projection.Repr.t
| Zfix of fconstr * stack
+ | Zprimitive of CPrimitives.t * pconstant * fconstr list * fconstr next_native_args
+ (* operator, constr def, arguments already seen (in rev order), next arguments *)
| Zshift of int
| Zupdate of fconstr
@@ -358,7 +363,7 @@ let append_stack v s =
if Int.equal (Array.length v) 0 then s else
match s with
| Zapp l :: s -> Zapp (Array.append v l) :: s
- | (ZcaseT _ | Zproj _ | Zfix _ | Zshift _ | Zupdate _) :: _ | [] ->
+ | (ZcaseT _ | Zproj _ | Zfix _ | Zshift _ | Zupdate _ | Zprimitive _) :: _ | [] ->
Zapp v :: s
(* Collapse the shifts in the stack *)
@@ -366,20 +371,20 @@ let zshift n s =
match (n,s) with
(0,_) -> s
| (_,Zshift(k)::s) -> Zshift(n+k)::s
- | (_,(ZcaseT _ | Zproj _ | Zfix _ | Zapp _ | Zupdate _) :: _) | _,[] -> Zshift(n)::s
+ | (_,(ZcaseT _ | Zproj _ | Zfix _ | Zapp _ | Zupdate _ | Zprimitive _) :: _) | _,[] -> Zshift(n)::s
let rec stack_args_size = function
| Zapp v :: s -> Array.length v + stack_args_size s
| Zshift(_)::s -> stack_args_size s
| Zupdate(_)::s -> stack_args_size s
- | (ZcaseT _ | Zproj _ | Zfix _) :: _ | [] -> 0
+ | (ZcaseT _ | Zproj _ | Zfix _ | Zprimitive _) :: _ | [] -> 0
(* Lifting. Preserves sharing (useful only for cell with norm=Red).
lft_fconstr always create a new cell, while lift_fconstr avoids it
when the lift is 0. *)
let rec lft_fconstr n ft =
match ft.term with
- | (FInd _|FConstruct _|FFlex(ConstKey _|VarKey _)) -> ft
+ | (FInd _|FConstruct _|FFlex(ConstKey _|VarKey _)|FInt _) -> ft
| FRel i -> {norm=Norm;term=FRel(i+n)}
| FLambda(k,tys,f,e) -> {norm=Cstr; term=FLambda(k,tys,f,subs_shft(n,e))}
| FFix(fx,e) -> {norm=Cstr; term=FFix(fx,subs_shft(n,e))}
@@ -411,7 +416,7 @@ let compact_stack head stk =
(** The stack contains [Zupdate] marks only if in sharing mode *)
let _ = update ~share:true m h'.norm h'.term in
strip_rec depth s
- | ((ZcaseT _ | Zproj _ | Zfix _ | Zapp _) :: _ | []) as stk -> zshift depth stk
+ | ((ZcaseT _ | Zproj _ | Zfix _ | Zapp _ | Zprimitive _) :: _ | []) as stk -> zshift depth stk
in
strip_rec 0 stk
@@ -447,6 +452,7 @@ let mk_clos e t =
| Meta _ | Sort _ -> { norm = Norm; term = FAtom t }
| Ind kn -> { norm = Norm; term = FInd kn }
| Construct kn -> { norm = Cstr; term = FConstruct kn }
+ | Int i -> {norm = Cstr; term = FInt i}
| (CoFix _|Lambda _|Fix _|Prod _|Evar _|App _|Case _|Cast _|LetIn _|Proj _) ->
{norm = Red; term = FCLOS(t,e)}
@@ -465,32 +471,34 @@ let mk_clos_vect env v = match v with
let ref_value_cache ({ i_cache = cache; _ }) tab ref =
try
- Some (KeyTable.find tab ref)
+ KeyTable.find tab ref
with Not_found ->
- try
- let body =
- match ref with
- | RelKey n ->
- let open! Context.Rel.Declaration in
- let i = n - 1 in
- let (d, _) =
- try Range.get cache.i_env.env_rel_context.env_rel_map i
- with Invalid_argument _ -> raise Not_found
- in
- begin match d with
- | LocalAssum _ -> raise Not_found
- | LocalDef (_, t, _) -> lift n t
- end
- | VarKey id -> assoc_defined id cache.i_env
- | ConstKey cst -> constant_value_in cache.i_env cst
+ let v =
+ try
+ let body =
+ match ref with
+ | RelKey n ->
+ let open! Context.Rel.Declaration in
+ let i = n - 1 in
+ let (d, _) =
+ try Range.get cache.i_env.env_rel_context.env_rel_map i
+ with Invalid_argument _ -> raise Not_found
+ in
+ begin match d with
+ | LocalAssum _ -> raise Not_found
+ | LocalDef (_, t, _) -> lift n t
+ end
+ | VarKey id -> assoc_defined id cache.i_env
+ | ConstKey cst -> constant_value_in cache.i_env cst
+ in
+ Def (inject body)
+ with
+ | NotEvaluableConst (IsPrimitive op) (* Const *) -> Primitive op
+ | Not_found (* List.assoc *)
+ | NotEvaluableConst _ (* Const *)
+ -> Undef None
in
- let v = inject body in
- KeyTable.add tab ref v;
- Some v
- with
- | Not_found (* List.assoc *)
- | NotEvaluableConst _ (* Const *)
- -> None
+ KeyTable.add tab ref v; v
(* The inverse of mk_clos: move back to constr *)
let rec to_constr lfts v =
@@ -559,6 +567,10 @@ let rec to_constr lfts v =
let subs = comp_subs lfts env in
mkEvar(ev,Array.map (fun a -> subst_constr subs a) args)
| FLIFT (k,a) -> to_constr (el_shft k lfts) a
+
+ | FInt i ->
+ Constr.mkInt i
+
| FCLOS (t,env) ->
if is_subs_id env && is_lift_id lfts then t
else
@@ -607,6 +619,10 @@ let rec zip m stk =
| Zupdate(rf)::s ->
(** The stack contains [Zupdate] marks only if in sharing mode *)
zip (update ~share:true rf m.norm m.term) s
+ | Zprimitive(_op,c,rargs,kargs)::s ->
+ let args = List.rev_append rargs (m::List.map snd kargs) in
+ let f = {norm = Red;term = FFlex (ConstKey c)} in
+ zip {norm=neutr m.norm; term = FApp (f, Array.of_list args)} s
let fapp_stack (m,stk) = zip m stk
@@ -628,7 +644,7 @@ let strip_update_shift_app_red head stk =
| Zupdate(m)::s ->
(** The stack contains [Zupdate] marks only if in sharing mode *)
strip_rec rstk (update ~share:true m h.norm h.term) depth s
- | ((ZcaseT _ | Zproj _ | Zfix _) :: _ | []) as stk ->
+ | ((ZcaseT _ | Zproj _ | Zfix _ | Zprimitive _) :: _ | []) as stk ->
(depth,List.rev rstk, stk)
in
strip_rec [] head 0 stk
@@ -656,7 +672,7 @@ let get_nth_arg head n stk =
| Zupdate(m)::s ->
(** The stack contains [Zupdate] mark only if in sharing mode *)
strip_rec rstk (update ~share:true m h.norm h.term) n s
- | ((ZcaseT _ | Zproj _ | Zfix _) :: _ | []) as s -> (None, List.rev rstk @ s) in
+ | ((ZcaseT _ | Zproj _ | Zfix _ | Zprimitive _) :: _ | []) as s -> (None, List.rev rstk @ s) in
strip_rec [] head n stk
(* Beta reduction: look for an applied argument in the stack.
@@ -678,24 +694,70 @@ let rec get_args n tys f e = function
else (* more lambdas *)
let etys = List.skipn na tys in
get_args (n-na) etys f (subs_cons(l,e)) s
- | ((ZcaseT _ | Zproj _ | Zfix _) :: _ | []) as stk ->
+ | ((ZcaseT _ | Zproj _ | Zfix _ | Zprimitive _) :: _ | []) as stk ->
(Inr {norm=Cstr;term=FLambda(n,tys,f,e)}, stk)
(* Eta expansion: add a reference to implicit surrounding lambda at end of stack *)
let rec eta_expand_stack = function
| (Zapp _ | Zfix _ | ZcaseT _ | Zproj _
- | Zshift _ | Zupdate _ as e) :: s ->
+ | Zshift _ | Zupdate _ | Zprimitive _ as e) :: s ->
e :: eta_expand_stack s
| [] ->
[Zshift 1; Zapp [|{norm=Norm; term= FRel 1}|]]
+(* Get the arguments of a native operator *)
+let rec skip_native_args rargs nargs =
+ match nargs with
+ | (kd, a) :: nargs' ->
+ if kd = CPrimitives.Kwhnf then rargs, nargs
+ else skip_native_args (a::rargs) nargs'
+ | [] -> rargs, []
+
+let get_native_args op c stk =
+ let kargs = CPrimitives.kind op in
+ let rec get_args rnargs kargs args =
+ match kargs, args with
+ | kd::kargs, a::args -> get_args ((kd,a)::rnargs) kargs args
+ | _, _ -> rnargs, kargs, args in
+ let rec strip_rec rnargs h depth kargs = function
+ | Zshift k :: s ->
+ strip_rec (List.map (fun (kd,f) -> kd,lift_fconstr k f) rnargs)
+ (lift_fconstr k h) (depth+k) kargs s
+ | Zapp args :: s' ->
+ begin match get_args rnargs kargs (Array.to_list args) with
+ | rnargs, [], [] ->
+ (skip_native_args [] (List.rev rnargs), s')
+ | rnargs, [], eargs ->
+ (skip_native_args [] (List.rev rnargs),
+ Zapp (Array.of_list eargs) :: s')
+ | rnargs, kargs, _ ->
+ strip_rec rnargs {norm = h.norm;term=FApp(h, args)} depth kargs s'
+ end
+ | Zupdate(m) :: s ->
+ strip_rec rnargs (update ~share:true m h.norm h.term) depth kargs s
+ | (Zprimitive _ | ZcaseT _ | Zproj _ | Zfix _) :: _ | [] -> assert false
+ in strip_rec [] {norm = Red;term = FFlex(ConstKey c)} 0 kargs stk
+
+let get_native_args1 op c stk =
+ match get_native_args op c stk with
+ | ((rargs, (kd,a):: nargs), stk) ->
+ assert (kd = CPrimitives.Kwhnf);
+ (rargs, a, nargs, stk)
+ | _ -> assert false
+
+let check_native_args op stk =
+ let nargs = CPrimitives.arity op in
+ let rargs = stack_args_size stk in
+ nargs <= rargs
+
+
(* Iota reduction: extract the arguments to be passed to the Case
branches *)
let rec reloc_rargs_rec depth = function
| Zapp args :: s ->
Zapp (lift_fconstr_vect depth args) :: reloc_rargs_rec depth s
| Zshift(k)::s -> if Int.equal k depth then s else reloc_rargs_rec (depth-k) s
- | ((ZcaseT _ | Zproj _ | Zfix _ | Zupdate _) :: _ | []) as stk -> stk
+ | ((ZcaseT _ | Zproj _ | Zfix _ | Zupdate _ | Zprimitive _) :: _ | []) as stk -> stk
let reloc_rargs depth stk =
if Int.equal depth 0 then stk else reloc_rargs_rec depth stk
@@ -712,7 +774,7 @@ let rec try_drop_parameters depth n = function
| [] ->
if Int.equal n 0 then []
else raise Not_found
- | (ZcaseT _ | Zproj _ | Zfix _ | Zupdate _) :: _ -> assert false
+ | (ZcaseT _ | Zproj _ | Zfix _ | Zupdate _ | Zprimitive _) :: _ -> assert false
(* strip_update_shift_app only produces Zapp and Zshift items *)
let drop_parameters depth n argstk =
@@ -757,7 +819,7 @@ let rec project_nth_arg n = function
let q = Array.length args in
if n >= q then project_nth_arg (n - q) s
else (* n < q *) args.(n)
- | (ZcaseT _ | Zproj _ | Zfix _ | Zupdate _ | Zshift _) :: _ | [] -> assert false
+ | (ZcaseT _ | Zproj _ | Zfix _ | Zupdate _ | Zshift _ | Zprimitive _) :: _ | [] -> assert false
(* After drop_parameters we have a purely applicative stack *)
@@ -814,7 +876,7 @@ let rec knh info m stk =
(* cases where knh stops *)
| (FFlex _|FLetIn _|FConstruct _|FEvar _|
- FCoFix _|FLambda _|FRel _|FAtom _|FInd _|FProd _) ->
+ FCoFix _|FLambda _|FRel _|FAtom _|FInd _|FProd _|FInt _) ->
(m, stk)
(* The same for pure terms *)
@@ -828,7 +890,7 @@ and knht info e t stk =
| Cast(a,_,_) -> knht info e a stk
| Rel n -> knh info (clos_rel e n) stk
| Proj (p, c) -> knh info { norm = Red; term = FProj (p, mk_clos e c) } stk
- | (Ind _|Const _|Construct _|Var _|Meta _ | Sort _) -> (mk_clos e t, stk)
+ | (Ind _|Const _|Construct _|Var _|Meta _ | Sort _ | Int _) -> (mk_clos e t, stk)
| CoFix cfx -> { norm = Cstr; term = FCoFix (cfx,e) }, stk
| Lambda _ -> { norm = Cstr; term = mk_lambda e t }, stk
| Prod (n, t, c) ->
@@ -837,6 +899,162 @@ and knht info e t stk =
{ norm = Red; term = FLetIn (n, mk_clos e b, mk_clos e t, c, e) }, stk
| Evar ev -> { norm = Red; term = FEvar (ev, e) }, stk
+let inject c = mk_clos (subs_id 0) c
+
+(************************************************************************)
+(* Reduction of Native operators *)
+
+open Primred
+
+module FNativeEntries =
+ struct
+ type elem = fconstr
+ type args = fconstr array
+ type evd = unit
+
+ let get = Array.get
+
+ let get_int () e =
+ match [@ocaml.warning "-4"] e.term with
+ | FInt i -> i
+ | _ -> raise Primred.NativeDestKO
+
+ let dummy = {norm = Norm; term = FRel 0}
+
+ let current_retro = ref Retroknowledge.empty
+ let defined_int = ref false
+ let fint = ref dummy
+
+ let init_int retro =
+ match retro.Retroknowledge.retro_int63 with
+ | Some c ->
+ defined_int := true;
+ fint := { norm = Norm; term = FFlex (ConstKey (Univ.in_punivs c)) }
+ | None -> defined_int := false
+
+ let defined_bool = ref false
+ let ftrue = ref dummy
+ let ffalse = ref dummy
+
+ let init_bool retro =
+ match retro.Retroknowledge.retro_bool with
+ | Some (ct,cf) ->
+ defined_bool := true;
+ ftrue := { norm = Cstr; term = FConstruct (Univ.in_punivs ct) };
+ ffalse := { norm = Cstr; term = FConstruct (Univ.in_punivs cf) }
+ | None -> defined_bool :=false
+
+ let defined_carry = ref false
+ let fC0 = ref dummy
+ let fC1 = ref dummy
+
+ let init_carry retro =
+ match retro.Retroknowledge.retro_carry with
+ | Some(c0,c1) ->
+ defined_carry := true;
+ fC0 := { norm = Cstr; term = FConstruct (Univ.in_punivs c0) };
+ fC1 := { norm = Cstr; term = FConstruct (Univ.in_punivs c1) }
+ | None -> defined_carry := false
+
+ let defined_pair = ref false
+ let fPair = ref dummy
+
+ let init_pair retro =
+ match retro.Retroknowledge.retro_pair with
+ | Some c ->
+ defined_pair := true;
+ fPair := { norm = Cstr; term = FConstruct (Univ.in_punivs c) }
+ | None -> defined_pair := false
+
+ let defined_cmp = ref false
+ let fEq = ref dummy
+ let fLt = ref dummy
+ let fGt = ref dummy
+
+ let init_cmp retro =
+ match retro.Retroknowledge.retro_cmp with
+ | Some (cEq, cLt, cGt) ->
+ defined_cmp := true;
+ fEq := { norm = Cstr; term = FConstruct (Univ.in_punivs cEq) };
+ fLt := { norm = Cstr; term = FConstruct (Univ.in_punivs cLt) };
+ fGt := { norm = Cstr; term = FConstruct (Univ.in_punivs cGt) }
+ | None -> defined_cmp := false
+
+ let defined_refl = ref false
+
+ let frefl = ref dummy
+
+ let init_refl retro =
+ match retro.Retroknowledge.retro_refl with
+ | Some crefl ->
+ defined_refl := true;
+ frefl := { norm = Cstr; term = FConstruct (Univ.in_punivs crefl) }
+ | None -> defined_refl := false
+
+ let init env =
+ current_retro := env.retroknowledge;
+ init_int !current_retro;
+ init_bool !current_retro;
+ init_carry !current_retro;
+ init_pair !current_retro;
+ init_cmp !current_retro;
+ init_refl !current_retro
+
+ let check_env env =
+ if not (!current_retro == env.retroknowledge) then init env
+
+ let check_int env =
+ check_env env;
+ assert (!defined_int)
+
+ let check_bool env =
+ check_env env;
+ assert (!defined_bool)
+
+ let check_carry env =
+ check_env env;
+ assert (!defined_carry && !defined_int)
+
+ let check_pair env =
+ check_env env;
+ assert (!defined_pair && !defined_int)
+
+ let check_cmp env =
+ check_env env;
+ assert (!defined_cmp)
+
+ let mkInt env i =
+ check_int env;
+ { norm = Norm; term = FInt i }
+
+ let mkBool env b =
+ check_bool env;
+ if b then !ftrue else !ffalse
+
+ let mkCarry env b e =
+ check_carry env;
+ {norm = Cstr;
+ term = FApp ((if b then !fC1 else !fC0),[|!fint;e|])}
+
+ let mkIntPair env e1 e2 =
+ check_pair env;
+ { norm = Cstr; term = FApp(!fPair, [|!fint;!fint;e1;e2|]) }
+
+ let mkLt env =
+ check_cmp env;
+ !fLt
+
+ let mkEq env =
+ check_cmp env;
+ !fEq
+
+ let mkGt env =
+ check_cmp env;
+ !fGt
+
+ end
+
+module FredNative = RedNative(FNativeEntries)
(************************************************************************)
@@ -849,16 +1067,21 @@ let rec knr info tab m stk =
| Inr lam, s -> (lam,s))
| FFlex(ConstKey (kn,_ as c)) when red_set info.i_flags (fCONST kn) ->
(match ref_value_cache info tab (ConstKey c) with
- Some v -> kni info tab v stk
- | None -> (set_norm m; (m,stk)))
+ | 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)))
| FFlex(VarKey id) when red_set info.i_flags (fVAR id) ->
(match ref_value_cache info tab (VarKey id) with
- Some v -> kni info tab v stk
- | None -> (set_norm m; (m,stk)))
+ | Def v -> kni info tab v stk
+ | Primitive _ -> assert false
+ | OpaqueDef _ | Undef _ -> (set_norm m; (m,stk)))
| FFlex(RelKey k) when red_set info.i_flags fDELTA ->
(match ref_value_cache info tab (RelKey k) with
- Some v -> kni info tab v stk
- | None -> (set_norm m; (m,stk)))
+ | Def v -> kni info tab v stk
+ | Primitive _ -> assert false
+ | OpaqueDef _ | Undef _ -> (set_norm m; (m,stk)))
| FConstruct((_ind,c),_u) ->
let use_match = red_set info.i_flags fMATCH in
let use_fix = red_set info.i_flags fFIX in
@@ -884,13 +1107,32 @@ let rec knr info tab m stk =
| (_, args, (((ZcaseT _|Zproj _)::_) as stk')) ->
let (fxe,fxbd) = contract_fix_vect m.term in
knit info tab fxe fxbd (args@stk')
- | (_,args, ((Zapp _ | Zfix _ | Zshift _ | Zupdate _) :: _ | [] as s)) -> (m,args@s))
+ | (_,args, ((Zapp _ | Zfix _ | Zshift _ | Zupdate _ | Zprimitive _) :: _ | [] as s)) -> (m,args@s))
| FLetIn (_,v,_,bd,e) when red_set info.i_flags fZETA ->
knit info tab (subs_cons([|v|],e)) bd stk
| FEvar(ev,env) ->
(match info.i_cache.i_sigma ev with
Some c -> knit info tab env c stk
| None -> (m,stk))
+ | FInt _ ->
+ (match [@ocaml.warning "-4"] strip_update_shift_app m stk with
+ | (_, _, Zprimitive(op,c,rargs,nargs)::s) ->
+ let (rargs, nargs) = skip_native_args (m::rargs) nargs in
+ begin match nargs with
+ | [] ->
+ let args = Array.of_list (List.rev rargs) in
+ begin match FredNative.red_prim (info_env info) () op args with
+ | Some m -> kni info tab m s
+ | None ->
+ let f = {norm = Whnf; term = FFlex (ConstKey c)} in
+ let m = {norm = Whnf; term = FApp(f,args)} in
+ (m,s)
+ end
+ | (kd,a)::nargs ->
+ assert (kd = CPrimitives.Kwhnf);
+ kni info tab a (Zprimitive(op,c,rargs,nargs)::s)
+ end
+ | (_, _, s) -> (m, s))
| FLOCKED | FRel _ | FAtom _ | FFlex (RelKey _ | ConstKey _ | VarKey _) | FInd _ | FApp _ | FProj _
| FFix _ | FCoFix _ | FCaseT _ | FLambda _ | FProd _ | FLetIn _ | FLIFT _
| FCLOS _ -> (m, stk)
@@ -927,6 +1169,12 @@ let rec zip_term zfun m stk =
zip_term zfun (lift n m) s
| Zupdate(_rf)::s ->
zip_term zfun m s
+ | Zprimitive(_,c,rargs, kargs)::s ->
+ let kargs = List.map (fun (_,a) -> zfun a) kargs in
+ let args =
+ List.fold_left (fun args a -> zfun a ::args) (m::kargs) rargs in
+ let h = mkApp (mkConstU c, Array.of_list args) in
+ zip_term zfun h s
(* Computes the strong normal form of a term.
1- Calls kni
@@ -972,7 +1220,7 @@ and norm_head info tab m =
| FProj (p,c) ->
mkProj (p, kl info tab c)
| FLOCKED | FRel _ | FAtom _ | FFlex _ | FInd _ | FConstruct _
- | FApp _ | FCaseT _ | FLIFT _ | FCLOS _ -> term_of_fconstr m
+ | FApp _ | FCaseT _ | FLIFT _ | FCLOS _ | FInt _ -> term_of_fconstr m
(* Initialization and then normalization *)
@@ -1015,9 +1263,9 @@ let unfold_reference info tab key =
| ConstKey (kn,_) ->
if red_set info.i_flags (fCONST kn) then
ref_value_cache info tab key
- else None
+ else Undef None
| VarKey i ->
if red_set info.i_flags (fVAR i) then
ref_value_cache info tab key
- else None
+ else Undef None
| RelKey _ -> ref_value_cache info tab key
diff --git a/kernel/cClosure.mli b/kernel/cClosure.mli
index 46be1bb279..bd04677374 100644
--- a/kernel/cClosure.mli
+++ b/kernel/cClosure.mli
@@ -10,6 +10,7 @@
open Names
open Constr
+open Declarations
open Environ
open Esubst
@@ -117,6 +118,7 @@ type fterm =
| FProd of Name.t * fconstr * constr * fconstr subs
| FLetIn of Name.t * fconstr * fconstr * constr * fconstr subs
| FEvar of existential * fconstr subs
+ | FInt of Uint63.t
| FLIFT of int * fconstr
| FCLOS of constr * fconstr subs
| FLOCKED
@@ -124,12 +126,15 @@ type fterm =
(***********************************************************************
s A [stack] is a context of arguments, arguments are pushed by
[append_stack] one array at a time *)
+type 'a next_native_args = (CPrimitives.arg_kind * 'a) list
type stack_member =
| Zapp of fconstr array
| ZcaseT of case_info * constr * constr array * fconstr subs
| Zproj of Projection.Repr.t
| Zfix of fconstr * stack
+ | Zprimitive of CPrimitives.t * pconstant * fconstr list * fconstr next_native_args
+ (* operator, constr def, reduced arguments rev, next arguments *)
| Zshift of int
| Zupdate of fconstr
@@ -138,6 +143,10 @@ and stack = stack_member list
val empty_stack : stack
val append_stack : fconstr array -> stack -> stack
+val check_native_args : CPrimitives.t -> stack -> bool
+val get_native_args1 : CPrimitives.t -> pconstant -> stack ->
+ fconstr list * fconstr * fconstr next_native_args * stack
+
val stack_args_size : stack -> int
val eta_expand_stack : stack -> stack
@@ -201,7 +210,7 @@ val eta_expand_ind_stack : env -> inductive -> fconstr -> stack ->
(** Conversion auxiliary functions to do step by step normalisation *)
(** [unfold_reference] unfolds references in a [fconstr] *)
-val unfold_reference : clos_infos -> clos_tab -> table_key -> fconstr option
+val unfold_reference : clos_infos -> clos_tab -> table_key -> fconstr constant_def
(***********************************************************************
i This is for lazy debug *)
diff --git a/kernel/cPrimitives.ml b/kernel/cPrimitives.ml
index 5b91a9b572..da5c4fb07b 100644
--- a/kernel/cPrimitives.ml
+++ b/kernel/cPrimitives.ml
@@ -9,85 +9,147 @@
(************************************************************************)
type t =
- | Int31head0
- | Int31tail0
- | Int31add
- | Int31sub
- | Int31mul
- | Int31div
- | Int31mod
-(*
- | Int31lsr
- | Int31lsl
- *)
- | Int31land
- | Int31lor
- | Int31lxor
- | Int31addc
- | Int31subc
- | Int31addcarryc
- | Int31subcarryc
- | Int31mulc
- | Int31diveucl
- | Int31div21
- | Int31addmuldiv
- | Int31eq
- | Int31lt
- | Int31le
- | Int31compare
+ | Int63head0
+ | Int63tail0
+ | Int63add
+ | Int63sub
+ | Int63mul
+ | Int63div
+ | Int63mod
+ | Int63lsr
+ | Int63lsl
+ | Int63land
+ | Int63lor
+ | Int63lxor
+ | Int63addc
+ | Int63subc
+ | Int63addCarryC
+ | Int63subCarryC
+ | Int63mulc
+ | Int63diveucl
+ | Int63div21
+ | Int63addMulDiv
+ | Int63eq
+ | Int63lt
+ | Int63le
+ | Int63compare
+
+let equal (p1 : t) (p2 : t) =
+ p1 == p2
let hash = function
- | Int31head0 -> 1
- | Int31tail0 -> 2
- | Int31add -> 3
- | Int31sub -> 4
- | Int31mul -> 5
- | Int31div -> 6
- | Int31mod -> 7
-(*
- | Int31lsr -> 8
- | Int31lsl -> 9
- *)
- | Int31land -> 10
- | Int31lor -> 11
- | Int31lxor -> 12
- | Int31addc -> 13
- | Int31subc -> 14
- | Int31addcarryc -> 15
- | Int31subcarryc -> 16
- | Int31mulc -> 17
- | Int31diveucl -> 18
- | Int31div21 -> 19
- | Int31addmuldiv -> 20
- | Int31eq -> 21
- | Int31lt -> 22
- | Int31le -> 23
- | Int31compare -> 24
+ | Int63head0 -> 1
+ | Int63tail0 -> 2
+ | Int63add -> 3
+ | Int63sub -> 4
+ | Int63mul -> 5
+ | Int63div -> 6
+ | Int63mod -> 7
+ | Int63lsr -> 8
+ | Int63lsl -> 9
+ | Int63land -> 10
+ | Int63lor -> 11
+ | Int63lxor -> 12
+ | Int63addc -> 13
+ | Int63subc -> 14
+ | Int63addCarryC -> 15
+ | Int63subCarryC -> 16
+ | Int63mulc -> 17
+ | Int63diveucl -> 18
+ | Int63div21 -> 19
+ | Int63addMulDiv -> 20
+ | Int63eq -> 21
+ | Int63lt -> 22
+ | Int63le -> 23
+ | Int63compare -> 24
+(* Should match names in nativevalues.ml *)
let to_string = function
- | Int31head0 -> "head0"
- | Int31tail0 -> "tail0"
- | Int31add -> "add"
- | Int31sub -> "sub"
- | Int31mul -> "mul"
- | Int31div -> "div"
- | Int31mod -> "mod"
-(*
- | Int31lsr -> "l_sr"
- | Int31lsl -> "l_sl"
- *)
- | Int31land -> "l_and"
- | Int31lor -> "l_or"
- | Int31lxor -> "l_xor"
- | Int31addc -> "addc"
- | Int31subc -> "subc"
- | Int31addcarryc -> "addcarryc"
- | Int31subcarryc -> "subcarryc"
- | Int31mulc -> "mulc"
- | Int31diveucl -> "diveucl"
- | Int31div21 -> "div21"
- | Int31addmuldiv -> "addmuldiv"
- | Int31eq -> "eq"
- | Int31lt -> "lt"
- | Int31le -> "le"
- | Int31compare -> "compare"
+ | Int63head0 -> "head0"
+ | Int63tail0 -> "tail0"
+ | Int63add -> "add"
+ | Int63sub -> "sub"
+ | Int63mul -> "mul"
+ | Int63div -> "div"
+ | Int63mod -> "rem"
+ | Int63lsr -> "l_sr"
+ | Int63lsl -> "l_sl"
+ | Int63land -> "l_and"
+ | Int63lor -> "l_or"
+ | Int63lxor -> "l_xor"
+ | Int63addc -> "addc"
+ | Int63subc -> "subc"
+ | Int63addCarryC -> "addCarryC"
+ | Int63subCarryC -> "subCarryC"
+ | Int63mulc -> "mulc"
+ | Int63diveucl -> "diveucl"
+ | Int63div21 -> "div21"
+ | Int63addMulDiv -> "addMulDiv"
+ | Int63eq -> "eq"
+ | Int63lt -> "lt"
+ | Int63le -> "le"
+ | Int63compare -> "compare"
+
+type arg_kind =
+ | Kparam (* not needed for the evaluation of the primitive when it reduces *)
+ | Kwhnf (* need to be reduced in whnf before reducing the primitive *)
+ | Karg (* no need to be reduced in whnf. example: [v] in [Array.set t i v] *)
+
+type args_red = arg_kind list
+
+(* Invariant only argument of type int63 or an inductive can
+ have kind Kwhnf *)
+
+let kind = function
+ | Int63head0 | Int63tail0 -> [Kwhnf]
+
+ | Int63add | Int63sub | Int63mul
+ | Int63div | Int63mod
+ | Int63lsr | Int63lsl
+ | Int63land | Int63lor | Int63lxor
+ | Int63addc | Int63subc
+ | Int63addCarryC | Int63subCarryC | Int63mulc | Int63diveucl
+ | Int63eq | Int63lt | Int63le | Int63compare -> [Kwhnf; Kwhnf]
+
+ | Int63div21 | Int63addMulDiv -> [Kwhnf; Kwhnf; Kwhnf]
+
+let arity = function
+ | Int63head0 | Int63tail0 -> 1
+ | Int63add | Int63sub | Int63mul
+ | Int63div | Int63mod
+ | Int63lsr | Int63lsl
+ | Int63land | Int63lor | Int63lxor
+ | Int63addc | Int63subc
+ | Int63addCarryC | Int63subCarryC | Int63mulc | Int63diveucl
+ | Int63eq | Int63lt | Int63le
+ | Int63compare -> 2
+
+ | Int63div21 | Int63addMulDiv -> 3
+
+(** Special Entries for Register **)
+
+type prim_ind =
+ | PIT_bool
+ | PIT_carry
+ | PIT_pair
+ | PIT_cmp
+
+type prim_type =
+ | PT_int63
+
+type op_or_type =
+ | OT_op of t
+ | OT_type of prim_type
+
+let prim_ind_to_string = function
+ | PIT_bool -> "bool"
+ | PIT_carry -> "carry"
+ | PIT_pair -> "pair"
+ | PIT_cmp -> "cmp"
+
+let prim_type_to_string = function
+ | PT_int63 -> "int63"
+
+let op_or_type_to_string = function
+ | OT_op op -> to_string op
+ | OT_type t -> prim_type_to_string t
diff --git a/kernel/cPrimitives.mli b/kernel/cPrimitives.mli
index 1e99a69d2f..3f8174bd7b 100644
--- a/kernel/cPrimitives.mli
+++ b/kernel/cPrimitives.mli
@@ -9,33 +9,62 @@
(************************************************************************)
type t =
- | Int31head0
- | Int31tail0
- | Int31add
- | Int31sub
- | Int31mul
- | Int31div
- | Int31mod
-(*
- | Int31lsr
- | Int31lsl
- *)
- | Int31land
- | Int31lor
- | Int31lxor
- | Int31addc
- | Int31subc
- | Int31addcarryc
- | Int31subcarryc
- | Int31mulc
- | Int31diveucl
- | Int31div21
- | Int31addmuldiv
- | Int31eq
- | Int31lt
- | Int31le
- | Int31compare
+ | Int63head0
+ | Int63tail0
+ | Int63add
+ | Int63sub
+ | Int63mul
+ | Int63div
+ | Int63mod
+ | Int63lsr
+ | Int63lsl
+ | Int63land
+ | Int63lor
+ | Int63lxor
+ | Int63addc
+ | Int63subc
+ | Int63addCarryC
+ | Int63subCarryC
+ | Int63mulc
+ | Int63diveucl
+ | Int63div21
+ | Int63addMulDiv
+ | Int63eq
+ | Int63lt
+ | Int63le
+ | Int63compare
+
+val equal : t -> t -> bool
+
+type arg_kind =
+ | Kparam (* not needed for the elavuation of the primitive*)
+ | Kwhnf (* need to be reduced in whnf before reducing the primitive *)
+ | Karg (* no need to be reduced in whnf *)
+
+type args_red = arg_kind list
val hash : t -> int
val to_string : t -> string
+
+val arity : t -> int
+
+val kind : t -> args_red
+
+(** Special Entries for Register **)
+
+type prim_ind =
+ | PIT_bool
+ | PIT_carry
+ | PIT_pair
+ | PIT_cmp
+
+type prim_type =
+ | PT_int63
+
+type op_or_type =
+ | OT_op of t
+ | OT_type of prim_type
+
+val prim_ind_to_string : prim_ind -> string
+val op_or_type_to_string : op_or_type -> string
diff --git a/kernel/cbytecodes.ml b/kernel/cbytecodes.ml
index c63795b295..7570004fe5 100644
--- a/kernel/cbytecodes.ml
+++ b/kernel/cbytecodes.ml
@@ -16,6 +16,7 @@
open Names
open Vmvalues
+open Constr
module Label =
struct
@@ -26,7 +27,6 @@ module Label =
let reset_label_counter () = counter := no
end
-
type instruction =
| Klabel of Label.t
| Kacc of int
@@ -59,46 +59,9 @@ type instruction =
| Ksequence of bytecodes * bytecodes
| Kproj of Projection.Repr.t
| Kensurestackcapacity of int
-(* spiwack: instructions concerning integers *)
| Kbranch of Label.t (* jump to label *)
- | Kaddint31 (* adds the int31 in the accu
- and the one ontop of the stack *)
- | Kaddcint31 (* makes the sum and keeps the carry *)
- | Kaddcarrycint31 (* sum +1, keeps the carry *)
- | Ksubint31 (* subtraction modulo *)
- | Ksubcint31 (* subtraction, keeps the carry *)
- | Ksubcarrycint31 (* subtraction -1, keeps the carry *)
- | Kmulint31 (* multiplication modulo *)
- | Kmulcint31 (* multiplication, result in two
- int31, for exact computation *)
- | Kdiv21int31 (* divides a double size integer
- (represented by an int31 in the
- accumulator and one on the top of
- the stack) by an int31. The result
- is a pair of the quotient and the
- rest.
- If the divisor is 0, it returns
- 0. *)
- | Kdivint31 (* euclidian division (returns a pair
- quotient,rest) *)
- | Kaddmuldivint31 (* generic operation for shifting and
- cycling. Takes 3 int31 i j and s,
- and returns x*2^s+y/(2^(31-s) *)
- | Kcompareint31 (* unsigned comparison of int31
- cf COMPAREINT31 in
- kernel/byterun/coq_interp.c
- for more info *)
- | Khead0int31 (* Give the numbers of 0 in head of a in31*)
- | Ktail0int31 (* Give the numbers of 0 in tail of a in31
- ie low bits *)
- | Kisconst of Label.t (* conditional jump *)
- | Kareconst of int*Label.t (* conditional jump *)
- | Kcompint31 (* dynamic compilation of int31 *)
- | Kdecompint31 (* dynamic decompilation of int31 *)
- | Klorint31 (* bitwise operations: or and xor *)
- | Klandint31
- | Klxorint31
-(* /spiwack *)
+ | Kprim of CPrimitives.t * pconstant option
+ | Kareint of int
and bytecodes = instruction list
@@ -110,53 +73,6 @@ type fv_elem =
type fv = fv_elem array
-(* spiwack: this exception is expected to be raised by function expecting
- closed terms. *)
-exception NotClosed
-
-
-module Fv_elem =
-struct
-type t = fv_elem
-
-let compare e1 e2 = match e1, e2 with
-| FVnamed id1, FVnamed id2 -> Id.compare id1 id2
-| FVnamed _, (FVrel _ | FVuniv_var _ | FVevar _) -> -1
-| FVrel _, FVnamed _ -> 1
-| FVrel r1, FVrel r2 -> Int.compare r1 r2
-| FVrel _, (FVuniv_var _ | FVevar _) -> -1
-| FVuniv_var i1, FVuniv_var i2 -> Int.compare i1 i2
-| FVuniv_var _i1, (FVnamed _ | FVrel _) -> 1
-| FVuniv_var _i1, FVevar _ -> -1
-| FVevar _, (FVnamed _ | FVrel _ | FVuniv_var _) -> 1
-| FVevar e1, FVevar e2 -> Evar.compare e1 e2
-
-end
-
-module FvMap = Map.Make(Fv_elem)
-
-(*spiwack: both type have been moved from Cbytegen because I needed then
- for the retroknowledge *)
-type vm_env = {
- size : int; (* longueur de la liste [n] *)
- fv_rev : fv_elem list; (* [fvn; ... ;fv1] *)
- fv_fwd : int FvMap.t; (* reverse mapping *)
- }
-
-
-type comp_env = {
- arity : int; (* arity of the current function, 0 if none *)
- nb_uni_stack : int ; (* number of universes on the stack, *)
- (* universes are always at the bottom. *)
- nb_stack : int; (* number of variables on the stack *)
- in_stack : int list; (* position in the stack *)
- nb_rec : int; (* number of mutually recursive functions *)
- pos_rec : instruction list; (* instruction d'acces pour les variables *)
- (* de point fix ou de cofix *)
- offset : int;
- in_env : vm_env ref (* The free variables of the expression *)
- }
-
(* --- Pretty print *)
open Pp
open Util
@@ -228,28 +144,10 @@ let rec pp_instr i =
| Kensurestackcapacity size -> str "growstack " ++ int size
- | Kaddint31 -> str "addint31"
- | Kaddcint31 -> str "addcint31"
- | Kaddcarrycint31 -> str "addcarrycint31"
- | Ksubint31 -> str "subint31"
- | Ksubcint31 -> str "subcint31"
- | Ksubcarrycint31 -> str "subcarrycint31"
- | Kmulint31 -> str "mulint31"
- | Kmulcint31 -> str "mulcint31"
- | Kdiv21int31 -> str "div21int31"
- | Kdivint31 -> str "divint31"
- | Kcompareint31 -> str "compareint31"
- | Khead0int31 -> str "head0int31"
- | Ktail0int31 -> str "tail0int31"
- | Kaddmuldivint31 -> str "addmuldivint31"
- | Kisconst lbl -> str "isconst " ++ int lbl
- | Kareconst(n,lbl) -> str "areconst " ++ int n ++ spc () ++ int lbl
- | Kcompint31 -> str "compint31"
- | Kdecompint31 -> str "decompint"
- | Klorint31 -> str "lorint31"
- | Klandint31 -> str "landint31"
- | Klxorint31 -> str "lxorint31"
+ | Kprim (op, id) -> str (CPrimitives.to_string op) ++ str " " ++
+ (match id with Some (id,_u) -> Constant.print id | None -> str "")
+ | Kareint n -> str "areint " ++ int n
and pp_bytecodes c =
match c with
diff --git a/kernel/cbytecodes.mli b/kernel/cbytecodes.mli
index 9c04c166a2..423e7bbe65 100644
--- a/kernel/cbytecodes.mli
+++ b/kernel/cbytecodes.mli
@@ -12,6 +12,7 @@
open Names
open Vmvalues
+open Constr
module Label :
sig
@@ -57,48 +58,15 @@ type instruction =
| Kproj of Projection.Repr.t
| Kensurestackcapacity of int
-(** spiwack: instructions concerning integers *)
| Kbranch of Label.t (** jump to label, is it needed ? *)
- | Kaddint31 (** adds the int31 in the accu
- and the one ontop of the stack *)
- | Kaddcint31 (** makes the sum and keeps the carry *)
- | Kaddcarrycint31 (** sum +1, keeps the carry *)
- | Ksubint31 (** subtraction modulo *)
- | Ksubcint31 (** subtraction, keeps the carry *)
- | Ksubcarrycint31 (** subtraction -1, keeps the carry *)
- | Kmulint31 (** multiplication modulo *)
- | Kmulcint31 (** multiplication, result in two
- int31, for exact computation *)
- | Kdiv21int31 (** divides a double size integer
- (represented by an int31 in the
- accumulator and one on the top of
- the stack) by an int31. The result
- is a pair of the quotient and the
- rest.
- If the divisor is 0, it returns
- 0. *)
- | Kdivint31 (** euclidian division (returns a pair
- quotient,rest) *)
- | Kaddmuldivint31 (** generic operation for shifting and
- cycling. Takes 3 int31 i j and s,
- and returns x*2^s+y/(2^(31-s) *)
- | Kcompareint31 (** unsigned comparison of int31
- cf COMPAREINT31 in
- kernel/byterun/coq_interp.c
- for more info *)
- | Khead0int31 (** Give the numbers of 0 in head of a in31*)
- | Ktail0int31 (** Give the numbers of 0 in tail of a in31
- ie low bits *)
- | Kisconst of Label.t (** conditional jump *)
- | Kareconst of int*Label.t (** conditional jump *)
- | Kcompint31 (** dynamic compilation of int31 *)
- | Kdecompint31 (** dynamix decompilation of int31 *)
- | Klorint31 (** bitwise operations: or and xor *)
- | Klandint31
- | Klxorint31
+ | Kprim of CPrimitives.t * pconstant option
+
+ | Kareint of int
and bytecodes = instruction list
+val pp_bytecodes : bytecodes -> Pp.t
+
type fv_elem =
FVnamed of Id.t
| FVrel of int
@@ -107,34 +75,4 @@ type fv_elem =
type fv = fv_elem array
-
-(** spiwack: this exception is expected to be raised by function expecting
- closed terms. *)
-exception NotClosed
-
-module FvMap : Map.S with type key = fv_elem
-
-(*spiwack: both type have been moved from Cbytegen because I needed them
- for the retroknowledge *)
-type vm_env = {
- size : int; (** length of the list [n] *)
- fv_rev : fv_elem list; (** [fvn; ... ;fv1] *)
- fv_fwd : int FvMap.t; (** reverse mapping *)
- }
-
-
-type comp_env = {
- arity : int; (* arity of the current function, 0 if none *)
- nb_uni_stack : int ; (** number of universes on the stack *)
- nb_stack : int; (** number of variables on the stack *)
- in_stack : int list; (** position in the stack *)
- nb_rec : int; (** number of mutually recursive functions *)
- (** (= nbr) *)
- pos_rec : instruction list; (** instruction d'acces pour les variables *)
- (** de point fix ou de cofix *)
- offset : int;
- in_env : vm_env ref (** the variables that are accessed *)
- }
-
-val pp_bytecodes : bytecodes -> Pp.t
val pp_fv_elem : fv_elem -> Pp.t
diff --git a/kernel/cbytegen.ml b/kernel/cbytegen.ml
index 73620ae578..b95a940c14 100644
--- a/kernel/cbytegen.ml
+++ b/kernel/cbytegen.ml
@@ -17,7 +17,6 @@ open Names
open Vmvalues
open Cbytecodes
open Cemitcodes
-open Cinstr
open Clambda
open Constr
open Declarations
@@ -97,6 +96,48 @@ open Environ
(* In Cfxe_t accumulators, we need to store [fcofixi] for testing *)
(* conversion of cofixpoints (which is intentional). *)
+module Fv_elem =
+struct
+type t = fv_elem
+
+let compare e1 e2 = match e1, e2 with
+| FVnamed id1, FVnamed id2 -> Id.compare id1 id2
+| FVnamed _, (FVrel _ | FVuniv_var _ | FVevar _) -> -1
+| FVrel _, FVnamed _ -> 1
+| FVrel r1, FVrel r2 -> Int.compare r1 r2
+| FVrel _, (FVuniv_var _ | FVevar _) -> -1
+| FVuniv_var i1, FVuniv_var i2 -> Int.compare i1 i2
+| FVuniv_var _, (FVnamed _ | FVrel _) -> 1
+| FVuniv_var _, FVevar _ -> -1
+| FVevar _, (FVnamed _ | FVrel _ | FVuniv_var _) -> 1
+| FVevar e1, FVevar e2 -> Evar.compare e1 e2
+
+end
+
+module FvMap = Map.Make(Fv_elem)
+
+(*spiwack: both type have been moved from Cbytegen because I needed then
+ for the retroknowledge *)
+type vm_env = {
+ size : int; (* longueur de la liste [n] *)
+ fv_rev : fv_elem list; (* [fvn; ... ;fv1] *)
+ fv_fwd : int FvMap.t; (* reverse mapping *)
+ }
+
+
+type comp_env = {
+ arity : int; (* arity of the current function, 0 if none *)
+ nb_uni_stack : int ; (* number of universes on the stack, *)
+ (* universes are always at the bottom. *)
+ nb_stack : int; (* number of variables on the stack *)
+ in_stack : int list; (* position in the stack *)
+ nb_rec : int; (* number of mutually recursive functions *)
+ pos_rec : instruction list; (* instruction d'acces pour les variables *)
+ (* de point fix ou de cofix *)
+ offset : int;
+ in_env : vm_env ref (* The free variables of the expression *)
+ }
+
module Config = struct
let stack_threshold = 256 (* see byterun/coq_memory.h *)
let stack_safety_margin = 15
@@ -391,7 +432,6 @@ let init_fun_code () = fun_code := []
(* Compilation of constructors and inductive types *)
-(* Inv: arity > 0 *)
(*
If [tag] hits the OCaml limitation for non constant constructors, we switch to
@@ -437,7 +477,7 @@ let comp_app comp_fun comp_arg cenv f args sz cont =
comp_fun cenv f (sz + nargs)
(Kappterm(nargs, k + nargs) :: (discard_dead_code cont)))
| None ->
- if nargs < 4 then
+ if nargs <= 4 then
comp_args comp_arg cenv args sz
(Kpush :: (comp_fun cenv f (sz+nargs) (Kapply nargs :: cont)))
else
@@ -476,15 +516,6 @@ let rec get_alias env kn =
| BCalias kn' -> get_alias env kn'
| _ -> kn)
-(* spiwack: additional function which allow different part of compilation of the
- 31-bit integers *)
-
-let make_areconst n else_lbl cont =
- if n <= 0 then
- cont
- else
- Kareconst (n, else_lbl)::cont
-
(* sz is the size of the local stack *)
let rec compile_lam env cenv lam sz cont =
set_max_stack_size sz;
@@ -495,6 +526,8 @@ let rec compile_lam env cenv lam sz cont =
| Lval v -> compile_structured_constant cenv (Const_val v) sz cont
+ | Luint i -> compile_structured_constant cenv (Const_uint i) sz cont
+
| Lproj (p,arg) ->
compile_lam env cenv arg sz (Kproj p :: cont)
@@ -629,6 +662,17 @@ let rec compile_lam env cenv lam sz cont =
compile_fv cenv fv.fv_rev sz
(Kclosurecofix(fv.size, init, lbl_types, lbl_bodies) :: cont)
+ | Lif(t, bt, bf) ->
+ let branch, cont = make_branch cont in
+ let lbl_true = Label.create() in
+ let lbl_false = Label.create() in
+ compile_lam env cenv t sz
+ (Kswitch([|lbl_true;lbl_false|],[||]) ::
+ Klabel lbl_false ::
+ compile_lam env cenv bf sz
+ (branch ::
+ Klabel lbl_true ::
+ compile_lam env cenv bt sz cont))
| Lcase(ci,rtbl,t,a,branches) ->
let ind = ci.ci_ind in
@@ -729,41 +773,9 @@ let rec compile_lam env cenv lam sz cont =
let cont = code_makeblock ~stack_size:(sz+arity-1) ~arity ~tag cont in
comp_args (compile_lam env) cenv args sz cont
- | Lprim (kn, ar, op, args) ->
- op_compilation env ar op kn cenv args sz cont
-
- | Luint v ->
- (match v with
- | UintVal i -> compile_structured_constant cenv (Const_b0 (Uint31.to_int i)) sz cont
- | UintDigits ds ->
- let nargs = Array.length ds in
- if Int.equal nargs 31 then
- let (escape,labeled_cont) = make_branch cont in
- let else_lbl = Label.create() in
- comp_args (compile_lam env) cenv ds sz
- ( Kisconst else_lbl::Kareconst(30,else_lbl)::Kcompint31::escape::Klabel else_lbl::Kmakeblock(31, 1)::labeled_cont)
- else
- let code_construct cont = (* spiwack: variant of the global code_construct
- which handles dynamic compilation of
- integers *)
- let f_cont =
- let else_lbl = Label.create () in
- [Kacc 0; Kpop 1; Kisconst else_lbl; Kareconst(30,else_lbl);
- Kcompint31; Kreturn 0; Klabel else_lbl; Kmakeblock(31, 1); Kreturn 0]
- in
- let lbl = Label.create() in
- fun_code := [Ksequence (add_grab 31 lbl f_cont,!fun_code)];
- Kclosure(lbl,0) :: cont
- in
- comp_app (fun _ _ _ cont -> code_construct cont)
- (compile_lam env) cenv () ds sz cont
- | UintDecomp t ->
- let escape_lbl, labeled_cont = label_code cont in
- compile_lam env cenv t sz ((Kisconst escape_lbl)::Kdecompint31::labeled_cont))
-
-
-(* spiwack : compilation of constants with their arguments.
- Makes a special treatment with 31-bit integer addition *)
+ | Lprim (kn, op, args) ->
+ comp_args (compile_lam env) cenv args sz (Kprim(op, kn)::cont)
+
and compile_get_global cenv (kn,u) sz cont =
set_max_stack_size sz;
if Univ.Instance.is_empty u then
@@ -800,43 +812,6 @@ and compile_constant env cenv kn u args sz cont =
comp_app (fun _ _ _ cont -> Kgetglobal kn :: cont)
compile_arg cenv () all sz cont
-(*template for n-ary operation, invariant: n>=1,
- the operations does the following :
- 1/ checks if all the arguments are constants (i.e. non-block values)
- 2/ if they are, uses the "op" instruction to execute
- 3/ if at least one is not, branches to the normal behavior:
- Kgetglobal (get_alias !global_env kn) *)
-and op_compilation env n op =
- let code_construct cenv kn sz cont =
- let f_cont =
- let else_lbl = Label.create () in
- Kareconst(n, else_lbl):: Kacc 0:: Kpop 1::
- op:: Kreturn 0:: Klabel else_lbl::
- (* works as comp_app with nargs = n and tailcall cont [Kreturn 0]*)
- compile_get_global cenv kn sz (
- Kappterm(n, n):: []) (* = discard_dead_code [Kreturn 0] *)
- in
- let lbl = Label.create () in
- fun_code := [Ksequence (add_grab n lbl f_cont, !fun_code)];
- Kclosure(lbl, 0)::cont
- in
- fun kn cenv args sz cont ->
- let nargs = Array.length args in
- if Int.equal nargs n then (*if it is a fully applied addition*)
- let (escape, labeled_cont) = make_branch cont in
- let else_lbl = Label.create () in
- assert (n < 4);
- comp_args (compile_lam env) cenv args sz
- (Kisconst else_lbl::(make_areconst (n-1) else_lbl
- (*Kaddint31::escape::Klabel else_lbl::Kpush::*)
- (op::escape::Klabel else_lbl::Kpush::
- (* works as comp_app with nargs < 4 and non-tailcall cont*)
- compile_get_global cenv kn (sz+n) (Kapply n::labeled_cont))))
- else
- comp_app (fun cenv _ sz cont -> code_construct cenv kn sz cont)
- (compile_lam env) cenv () args sz cont
-
-
let is_univ_copy max u =
let u = Univ.Instance.to_array u in
if Array.length u = max then
@@ -903,7 +878,7 @@ let compile ~fail_on_error ?universes:(universes=0) env c =
fn msg; None
let compile_constant_body ~fail_on_error env univs = function
- | Undef _ | OpaqueDef _ -> Some BCconstant
+ | Undef _ | OpaqueDef _ | Primitive _ -> Some BCconstant
| Def sb ->
let body = Mod_subst.force_constr sb in
let instance_size =
@@ -923,41 +898,3 @@ let compile_constant_body ~fail_on_error env univs = function
(* Shortcut of the previous function used during module strengthening *)
let compile_alias kn = BCalias (Constant.make1 (Constant.canonical kn))
-
-(*(* template compilation for 2ary operation, it probably possible
- to make a generic such function with arity abstracted *)
-let op2_compilation op =
- let code_construct normal cont = (*kn cont =*)
- let f_cont =
- let else_lbl = Label.create () in
- Kareconst(2, else_lbl):: Kacc 0:: Kpop 1::
- op:: Kreturn 0:: Klabel else_lbl::
- (* works as comp_app with nargs = 2 and tailcall cont [Kreturn 0]*)
- (*Kgetglobal (get_alias !global_env kn):: *)
- normal::
- Kappterm(2, 2):: [] (* = discard_dead_code [Kreturn 0] *)
- in
- let lbl = Label.create () in
- fun_code := [Ksequence (add_grab 2 lbl f_cont, !fun_code)];
- Kclosure(lbl, 0)::cont
- in
- fun normal fc _ cenv args sz cont ->
- if not fc then raise Not_found else
- let nargs = Array.length args in
- if nargs=2 then (*if it is a fully applied addition*)
- let (escape, labeled_cont) = make_branch cont in
- let else_lbl = Label.create () in
- comp_args compile_constr cenv args sz
- (Kisconst else_lbl::(make_areconst 1 else_lbl
- (*Kaddint31::escape::Klabel else_lbl::Kpush::*)
- (op::escape::Klabel else_lbl::Kpush::
- (* works as comp_app with nargs = 2 and non-tailcall cont*)
- (*Kgetglobal (get_alias !global_env kn):: *)
- normal::
- Kapply 2::labeled_cont)))
- else if nargs=0 then
- code_construct normal cont
- else
- comp_app (fun _ _ _ cont -> code_construct normal cont)
- compile_constr cenv () args sz cont *)
-
diff --git a/kernel/cbytegen.mli b/kernel/cbytegen.mli
index 57d3e6fc27..b1b55aef48 100644
--- a/kernel/cbytegen.mli
+++ b/kernel/cbytegen.mli
@@ -20,7 +20,8 @@ val compile : fail_on_error:bool ->
(** init, fun, fv *)
val compile_constant_body : fail_on_error:bool ->
- env -> constant_universes -> constant_def -> body_code option
+ env -> constant_universes -> Constr.t Mod_subst.substituted constant_def ->
+ body_code option
(** Shortcut of the previous function used during module strengthening *)
diff --git a/kernel/cemitcodes.ml b/kernel/cemitcodes.ml
index 50f5607e31..a84a7c0cf9 100644
--- a/kernel/cemitcodes.ml
+++ b/kernel/cemitcodes.ml
@@ -18,6 +18,7 @@ open Vmvalues
open Cbytecodes
open Copcodes
open Mod_subst
+open CPrimitives
type emitcodes = String.t
@@ -129,6 +130,8 @@ let out_word env b1 b2 b3 b4 =
let out env opcode =
out_word env opcode 0 0 0
+let is_immed i = Uint63.le (Uint63.of_int i) Uint63.maxuint31
+
let out_int env n =
out_word env n (n asr 8) (n asr 16) (n asr 24)
@@ -198,6 +201,39 @@ let slot_for_proj_name env p =
(* Emission of one instruction *)
+let nocheck_prim_op = function
+ | Int63add -> opADDINT63
+ | Int63sub -> opSUBINT63
+ | Int63lt -> opLTINT63
+ | Int63le -> opLEINT63
+ | _ -> assert false
+
+
+let check_prim_op = function
+ | Int63head0 -> opCHECKHEAD0INT63
+ | Int63tail0 -> opCHECKTAIL0INT63
+ | Int63add -> opCHECKADDINT63
+ | Int63sub -> opCHECKSUBINT63
+ | Int63mul -> opCHECKMULINT63
+ | Int63div -> opCHECKDIVINT63
+ | Int63mod -> opCHECKMODINT63
+ | Int63lsr -> opCHECKLSRINT63
+ | Int63lsl -> opCHECKLSLINT63
+ | Int63land -> opCHECKLANDINT63
+ | Int63lor -> opCHECKLORINT63
+ | Int63lxor -> opCHECKLXORINT63
+ | Int63addc -> opCHECKADDCINT63
+ | Int63subc -> opCHECKSUBCINT63
+ | Int63addCarryC -> opCHECKADDCARRYCINT63
+ | Int63subCarryC -> opCHECKSUBCARRYCINT63
+ | Int63mulc -> opCHECKMULCINT63
+ | Int63diveucl -> opCHECKDIVEUCLINT63
+ | Int63div21 -> opCHECKDIV21INT63
+ | Int63addMulDiv -> opCHECKADDMULDIVINT63
+ | Int63eq -> opCHECKEQINT63
+ | Int63lt -> opCHECKLTINT63
+ | Int63le -> opCHECKLEINT63
+ | Int63compare -> opCHECKCOMPAREINT63
let emit_instr env = function
| Klabel lbl -> define_label env lbl
@@ -218,7 +254,7 @@ let emit_instr env = function
| Kpush_retaddr lbl ->
out env opPUSH_RETADDR; out_label env lbl
| Kapply n ->
- if n < 4 then out env(opAPPLY1 + n - 1) else (out env opAPPLY; out_int env n)
+ if n <= 4 then out env(opAPPLY1 + n - 1) else (out env opAPPLY; out_int env n)
| Kappterm(n, sz) ->
if n < 4 then (out env(opAPPTERM1 + n - 1); out_int env sz)
else (out env opAPPTERM; out_int env n; out_int env sz)
@@ -250,7 +286,7 @@ let emit_instr env = function
Array.iter (out_label_with_orig env org) lbl_bodies
| Kgetglobal q ->
out env opGETGLOBAL; slot_for_getglobal env q
- | Kconst (Const_b0 i) ->
+ | Kconst (Const_b0 i) when is_immed i ->
if i >= 0 && i <= 3
then out env (opCONST0 + i)
else (out env opCONSTINT; out_int env i)
@@ -287,32 +323,20 @@ let emit_instr env = function
| Ksequence _ -> invalid_arg "Cemitcodes.emit_instr"
| Kproj p -> out env opPROJ; out_int env (Projection.Repr.arg p); slot_for_proj_name env p
| Kensurestackcapacity size -> out env opENSURESTACKCAPACITY; out_int env size
- (* spiwack *)
| Kbranch lbl -> out env opBRANCH; out_label env lbl
- | Kaddint31 -> out env opADDINT31
- | Kaddcint31 -> out env opADDCINT31
- | Kaddcarrycint31 -> out env opADDCARRYCINT31
- | Ksubint31 -> out env opSUBINT31
- | Ksubcint31 -> out env opSUBCINT31
- | Ksubcarrycint31 -> out env opSUBCARRYCINT31
- | Kmulint31 -> out env opMULINT31
- | Kmulcint31 -> out env opMULCINT31
- | Kdiv21int31 -> out env opDIV21INT31
- | Kdivint31 -> out env opDIVINT31
- | Kaddmuldivint31 -> out env opADDMULDIVINT31
- | Kcompareint31 -> out env opCOMPAREINT31
- | Khead0int31 -> out env opHEAD0INT31
- | Ktail0int31 -> out env opTAIL0INT31
- | Kisconst lbl -> out env opISCONST; out_label env lbl
- | Kareconst(n,lbl) -> out env opARECONST; out_int env n; out_label env lbl
- | Kcompint31 -> out env opCOMPINT31
- | Kdecompint31 -> out env opDECOMPINT31
- | Klorint31 -> out env opORINT31
- | Klandint31 -> out env opANDINT31
- | Klxorint31 -> out env opXORINT31
- (*/spiwack *)
- | Kstop ->
- out env opSTOP
+ | Kprim (op,None) ->
+ out env (nocheck_prim_op op)
+
+ | Kprim(op,Some (q,_u)) ->
+ out env (check_prim_op op);
+ slot_for_getglobal env q
+
+ | Kareint 1 -> out env opISINT
+ | Kareint 2 -> out env opAREINT2;
+
+ | Kstop -> out env opSTOP
+
+ | Kareint _ -> assert false
(* Emission of a current list and remaining lists of instructions. Include some peephole optimization. *)
@@ -337,7 +361,7 @@ let rec emit env insns remaining = match insns with
emit env c remaining
| Kpush :: Kgetglobal id :: c ->
out env opPUSHGETGLOBAL; slot_for_getglobal env id; emit env c remaining
- | Kpush :: Kconst (Const_b0 i) :: c ->
+ | Kpush :: Kconst (Const_b0 i) :: c when is_immed i ->
if i >= 0 && i <= 3
then out env (opPUSHCONST0 + i)
else (out env opPUSHCONSTINT; out_int env i);
@@ -360,7 +384,7 @@ type to_patch = emitcodes * patches * fv
(* Substitution *)
let subst_strcst s sc =
match sc with
- | Const_sort _ | Const_b0 _ | Const_univ_level _ | Const_val _ -> sc
+ | Const_sort _ | Const_b0 _ | Const_univ_level _ | Const_val _ | Const_uint _ -> sc
| Const_ind ind -> let kn,i = ind in Const_ind (subst_mind s kn, i)
let subst_reloc s ri =
diff --git a/kernel/cemitcodes.mli b/kernel/cemitcodes.mli
index 39ddf4a047..41cc641dc8 100644
--- a/kernel/cemitcodes.mli
+++ b/kernel/cemitcodes.mli
@@ -1,3 +1,10 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
open Names
open Vmvalues
open Cbytecodes
diff --git a/kernel/cinstr.mli b/kernel/cinstr.mli
deleted file mode 100644
index dca1757b7d..0000000000
--- a/kernel/cinstr.mli
+++ /dev/null
@@ -1,52 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-open Names
-open Constr
-open Vmvalues
-open Cbytecodes
-
-(** This file defines the lambda code for the bytecode compiler. It has been
-extracted from Clambda.ml because of the retroknowledge architecture. *)
-
-type uint =
- | UintVal of Uint31.t
- | UintDigits of lambda array
- | UintDecomp of lambda
-
-and lambda =
- | Lrel of Name.t * int
- | Lvar of Id.t
- | Levar of Evar.t * lambda array
- | Lprod of lambda * lambda
- | Llam of Name.t array * lambda
- | Llet of Name.t * lambda * lambda
- | Lapp of lambda * lambda array
- | Lconst of pconstant
- | Lprim of pconstant * int (* arity *) * instruction * lambda array
- | Lcase of case_info * reloc_table * lambda * lambda * lam_branches
- | Lfix of (int array * int) * fix_decl
- | Lcofix of int * fix_decl (* must be in eta-expanded form *)
- | Lmakeblock of int * lambda array
- | Lval of structured_values
- | Lsort of Sorts.t
- | Lind of pinductive
- | Lproj of Projection.Repr.t * lambda
- | Lint of int
- | Luint of uint
-
-(* Cofixpoints have to be in eta-expanded form for their call-by-need evaluation
-to be correct. Otherwise, memoization of previous evaluations will be applied
-again to extra arguments (see #7333). *)
-
-and lam_branches =
- { constant_branches : lambda array;
- nonconstant_branches : (Name.t array * lambda) array }
-
-and fix_decl = Name.t array * lambda array * lambda array
diff --git a/kernel/clambda.ml b/kernel/clambda.ml
index 1e4dbfd418..5c21a5ec25 100644
--- a/kernel/clambda.ml
+++ b/kernel/clambda.ml
@@ -5,13 +5,44 @@ open Term
open Constr
open Declarations
open Vmvalues
-open Cbytecodes
-open Cinstr
open Environ
open Pp
let pr_con sp = str(Names.Label.to_string (Constant.label sp))
+type lambda =
+ | Lrel of Name.t * int
+ | Lvar of Id.t
+ | Levar of Evar.t * lambda array
+ | Lprod of lambda * lambda
+ | Llam of Name.t array * lambda
+ | Llet of Name.t * lambda * lambda
+ | Lapp of lambda * lambda array
+ | Lconst of pconstant
+ | Lprim of pconstant option * CPrimitives.t * lambda array
+ (* No check if None *)
+ | Lcase of case_info * reloc_table * lambda * lambda * lam_branches
+ | Lif of lambda * lambda * lambda
+ | Lfix of (int array * int) * fix_decl
+ | Lcofix of int * fix_decl
+ | Lint of int
+ | Lmakeblock of int * lambda array
+ | Luint of Uint63.t
+ | Lval of structured_values
+ | Lsort of Sorts.t
+ | Lind of pinductive
+ | Lproj of Projection.Repr.t * lambda
+
+(* We separate branches for constant and non-constant constructors. If the OCaml
+ limitation on non-constant constructors is reached, remaining branches are
+ stored in [extra_branches]. *)
+and lam_branches =
+ { constant_branches : lambda array;
+ nonconstant_branches : (Name.t array * lambda) array }
+(* extra_branches : (name array * lambda) array } *)
+
+and fix_decl = Name.t array * lambda array * lambda array
+
(** Printing **)
let pp_names ids =
@@ -77,6 +108,10 @@ let rec pp_lam lam =
pp_names ids ++ str " => " ++ pp_lam c)
(Array.to_list branches.nonconstant_branches)))
++ cut() ++ str "end")
+ | Lif (t, bt, bf) ->
+ v 0 (str "(if " ++ pp_lam t ++
+ cut () ++ str "then " ++ pp_lam bt ++
+ cut() ++ str "else " ++ pp_lam bf ++ str ")")
| Lfix((t,i),(lna,tl,bl)) ->
let fixl = Array.mapi (fun i id -> (id,t.(i),tl.(i),bl.(i))) lna in
hov 1
@@ -104,22 +139,26 @@ let rec pp_lam lam =
(str "(makeblock " ++ int tag ++ spc() ++
prlist_with_sep spc pp_lam (Array.to_list args) ++
str")")
+ | Luint i -> str (Uint63.to_string i)
| Lval _ -> str "values"
| Lsort s -> pp_sort s
| Lind ((mind,i), _) -> MutInd.print mind ++ str"#" ++ int i
- | Lprim((kn,_u),_ar,_op,args) ->
- hov 1
- (str "(PRIM " ++ pr_con kn ++ spc() ++
- prlist_with_sep spc pp_lam (Array.to_list args) ++
- str")")
+ | Lprim(Some (kn,_u),_op,args) ->
+ hov 1
+ (str "(PRIM " ++ pr_con kn ++ spc() ++
+ prlist_with_sep spc pp_lam (Array.to_list args) ++
+ str")")
+ | Lprim(None,op,args) ->
+ hov 1
+ (str "(PRIM_NC " ++ str (CPrimitives.to_string op) ++ spc() ++
+ prlist_with_sep spc pp_lam (Array.to_list args) ++
+ str")")
| Lproj(p,arg) ->
hov 1
(str "(proj " ++ Projection.Repr.print p ++ str "(" ++ pp_lam arg
++ str ")")
| Lint i ->
Pp.(str "(int:" ++ int i ++ str ")")
- | Luint _ ->
- str "(uint)"
(*s Constructors *)
@@ -151,9 +190,9 @@ let shift subst = subs_shft (1, subst)
(* A generic map function *)
-let rec map_lam_with_binders g f n lam =
+let map_lam_with_binders g f n lam =
match lam with
- | Lrel _ | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ | Lint _ -> lam
+ | Lrel _ | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ | Lint _ | Luint _ -> lam
| Levar (evk, args) ->
let args' = Array.Smart.map (f n) args in
if args == args' then lam else Levar (evk, args')
@@ -192,6 +231,11 @@ let rec map_lam_with_binders g f n lam =
in
if t == t' && a == a' && branches == branches' then lam else
Lcase(ci,rtbl,t',a',branches')
+ | Lif(t,bt,bf) ->
+ let t' = f n t in
+ let bt' = f n bt in
+ let bf' = f n bf in
+ if t == t' && bt == bt' && bf == bf' then lam else Lif(t',bt',bf')
| Lfix(init,(ids,ltypes,lbodies)) ->
let ltypes' = Array.Smart.map (f n) ltypes in
let lbodies' = Array.Smart.map (f (g (Array.length ids) n)) lbodies in
@@ -205,25 +249,12 @@ let rec map_lam_with_binders g f n lam =
| Lmakeblock(tag,args) ->
let args' = Array.Smart.map (f n) args in
if args == args' then lam else Lmakeblock(tag,args')
- | Lprim(kn,ar,op,args) ->
+ | Lprim(kn,op,args) ->
let args' = Array.Smart.map (f n) args in
- if args == args' then lam else Lprim(kn,ar,op,args')
+ if args == args' then lam else Lprim(kn,op,args')
| Lproj(p,arg) ->
let arg' = f n arg in
if arg == arg' then lam else Lproj(p,arg')
- | Luint u ->
- let u' = map_uint g f n u in
- if u == u' then lam else Luint u'
-
-and map_uint _g f n u =
- match u with
- | UintVal _ -> u
- | UintDigits(args) ->
- let args' = Array.Smart.map (f n) args in
- if args == args' then u else UintDigits(args')
- | UintDecomp(a) ->
- let a' = f n a in
- if a == a' then u else UintDecomp(a')
(*s Lift and substitution *)
@@ -271,28 +302,58 @@ let lam_subst_args subst args =
let can_subst lam =
match lam with
- | Lrel _ | Lvar _ | Lconst _
+ | Lrel _ | Lvar _ | Lconst _ | Luint _
| Lval _ | Lsort _ | Lind _ -> true
| _ -> false
+
+let can_merge_if bt bf =
+ match bt, bf with
+ | Llam(_idst,_), Llam(_idsf,_) -> true
+ | _ -> false
+
+let merge_if t bt bf =
+ let (idst,bodyt) = decompose_Llam bt in
+ let (idsf,bodyf) = decompose_Llam bf in
+ let nt = Array.length idst in
+ let nf = Array.length idsf in
+ let common,idst,idsf =
+ if nt = nf then idst, [||], [||]
+ else
+ if nt < nf then idst,[||], Array.sub idsf nt (nf - nt)
+ else idsf, Array.sub idst nf (nt - nf), [||] in
+ Llam(common,
+ Lif(lam_lift (Array.length common) t,
+ mkLlam idst bodyt,
+ mkLlam idsf bodyf))
+
+
let rec simplify subst lam =
match lam with
| Lrel(id,i) -> lam_subst_rel lam id i subst
| Llet(id,def,body) ->
- let def' = simplify subst def in
- if can_subst def' then simplify (cons def' subst) body
- else
- let body' = simplify (lift subst) body in
- if def == def' && body == body' then lam
- else Llet(id,def',body')
+ let def' = simplify subst def in
+ if can_subst def' then simplify (cons def' subst) body
+ else
+ let body' = simplify (lift subst) body in
+ if def == def' && body == body' then lam
+ else Llet(id,def',body')
| Lapp(f,args) ->
- begin match simplify_app subst f subst args with
+ begin match simplify_app subst f subst args with
| Lapp(f',args') when f == f' && args == args' -> lam
| lam' -> lam'
- end
+ end
+ | Lif(t,bt,bf) ->
+ let t' = simplify subst t in
+ let bt' = simplify subst bt in
+ let bf' = simplify subst bf in
+ if can_merge_if bt' bf' then merge_if t' bt' bf'
+ else
+ if t == t' && bt == bt' && bf == bf' then lam
+ else Lif(t',bt',bf')
| _ -> map_lam_with_binders liftn simplify subst lam
and simplify_app substf f substa args =
@@ -352,7 +413,7 @@ let rec occurrence k kind lam =
if n = k then
if kind then false else raise Not_found
else kind
- | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ | Lint _ -> kind
+ | Lvar _ | Lconst _ | Lval _ | Lsort _ | Lind _ | Lint _ | Luint _ -> kind
| Levar (_, args) ->
occurrence_args k kind args
| Lprod(dom, codom) ->
@@ -363,7 +424,7 @@ let rec occurrence k kind lam =
occurrence (k+1) (occurrence k kind def) body
| Lapp(f, args) ->
occurrence_args k (occurrence k kind f) args
- | Lprim(_,_,_,args) | Lmakeblock(_,args) ->
+ | Lprim(_,_,args) | Lmakeblock(_,args) ->
occurrence_args k kind args
| Lcase(_ci,_rtbl,t,a,branches) ->
let kind = occurrence k (occurrence k kind t) a in
@@ -374,6 +435,9 @@ let rec occurrence k kind lam =
in
Array.iter on_b branches.nonconstant_branches;
!r
+ | Lif (t, bt, bf) ->
+ let kind = occurrence k kind t in
+ kind && occurrence k kind bt && occurrence k kind bf
| Lfix(_,(ids,ltypes,lbodies))
| Lcofix(_,(ids,ltypes,lbodies)) ->
let kind = occurrence_args k kind ltypes in
@@ -381,17 +445,10 @@ let rec occurrence k kind lam =
kind
| Lproj(_,arg) ->
occurrence k kind arg
- | Luint u -> occurrence_uint k kind u
and occurrence_args k kind args =
Array.fold_left (occurrence k) kind args
-and occurrence_uint k kind u =
- match u with
- | UintVal _ -> kind
- | UintDigits args -> occurrence_args k kind args
- | UintDecomp t -> occurrence k kind t
-
let occur_once lam =
try let _ = occurrence 1 true lam in true
with Not_found -> false
@@ -439,11 +496,12 @@ let check_compilable ib =
let is_value lc =
match lc with
- | Lval _ | Lint _ -> true
+ | Lval _ | Lint _ | Luint _ -> true
| _ -> false
let get_value lc =
match lc with
+ | Luint i -> val_of_uint i
| Lval v -> v
| Lint i -> val_of_int i
| _ -> raise Not_found
@@ -491,26 +549,18 @@ let rec get_alias env kn =
(* Compilation of primitive *)
-let _h = Name(Id.of_string "f")
+let prim kn p args =
+ Lprim(Some kn, p, args)
-(*
let expand_prim kn op arity =
let ids = Array.make arity Anonymous in
let args = make_args arity 1 in
Llam(ids, prim kn op args)
-*)
-let compile_prim n op kn fc args =
- if not fc then raise Not_found
- else
- Lprim(kn, n, op, args)
-
- (*
- let (nparams, arity) = CPrimitives.arity op in
- let expected = nparams + arity in
- if Array.length args >= expected then prim kn op args
- else mkLapp (expand_prim kn op expected) args
-*)
+let lambda_of_prim kn op args =
+ let arity = CPrimitives.arity op in
+ if Array.length args >= arity then prim kn op args
+ else mkLapp (expand_prim kn op arity) args
(*i Global environment *)
@@ -661,13 +711,6 @@ let rec lambda_of_constr env c =
(* translation of the argument *)
let la = lambda_of_constr env a in
- let gr = GlobRef.IndRef ind in
- let la =
- try
- Retroknowledge.get_vm_before_match_info env.global_env.retroknowledge
- gr la
- with Not_found -> la
- in
(* translation of the type *)
let lt = lambda_of_constr env t in
(* translation of branches *)
@@ -713,88 +756,30 @@ let rec lambda_of_constr env c =
let lc = lambda_of_constr env c in
Lproj (Projection.repr p,lc)
+ | Int i -> Luint i
+
and lambda_of_app env f args =
match Constr.kind f with
- | Const (kn,_u as c) ->
- let kn = get_alias env.global_env kn in
- (* spiwack: checks if there is a specific way to compile the constant
- if there is not, Not_found is raised, and the function
- falls back on its normal behavior *)
- (try
- (* We delay the compilation of arguments to avoid an exponential behavior *)
- let f = Retroknowledge.get_vm_compiling_info env.global_env.retroknowledge
- (GlobRef.ConstRef kn) in
- let args = lambda_of_args env 0 args in
- f args
- with Not_found ->
- let cb = lookup_constant kn env.global_env in
- begin match cb.const_body with
+ | Const (kn,u as c) ->
+ let kn = get_alias env.global_env kn in
+ let cb = lookup_constant kn env.global_env in
+ begin match cb.const_body with
+ | Primitive op -> lambda_of_prim (kn,u) op (lambda_of_args env 0 args)
| Def csubst when cb.const_inline_code ->
- lambda_of_app env (Mod_subst.force_constr csubst) args
+ lambda_of_app env (Mod_subst.force_constr csubst) args
| Def _ | OpaqueDef _ | Undef _ -> mkLapp (Lconst c) (lambda_of_args env 0 args)
- end)
+ end
| Construct (c,_) ->
- let tag, nparams, arity = Renv.get_construct_info env c in
- let nargs = Array.length args in
- let gr = GlobRef.ConstructRef c in
- if Int.equal (nparams + arity) nargs then (* fully applied *)
- (* spiwack: *)
- (* 1/ tries to compile the constructor in an optimal way,
- it is supposed to work only if the arguments are
- all fully constructed, fails with Cbytecodes.NotClosed.
- it can also raise Not_found when there is no special
- treatment for this constructor
- for instance: tries to to compile an integer of the
- form I31 D1 D2 ... D31 to [D1D2...D31] as
- a processor number (a caml number actually) *)
- try
- try
- Retroknowledge.get_vm_constant_static_info
- env.global_env.retroknowledge
- gr args
- with NotClosed ->
- (* 2/ if the arguments are not all closed (this is
- expectingly (and it is currently the case) the only
- reason why this exception is raised) tries to
- give a clever, run-time behavior to the constructor.
- Raises Not_found if there is no special treatment
- for this integer.
- this is done in a lazy fashion, using the constructor
- Bspecial because it needs to know the continuation
- and such, which can't be done at this time.
- for instance, for int31: if one of the digit is
- not closed, it's not impossible that the number
- gets fully instantiated at run-time, thus to ensure
- uniqueness of the representation in the vm
- it is necessary to try and build a caml integer
- during the execution *)
- let rargs = Array.sub args nparams arity in
- let args = lambda_of_args env nparams rargs in
- Retroknowledge.get_vm_constant_dynamic_info
- env.global_env.retroknowledge
- gr args
- with Not_found ->
- (* 3/ if no special behavior is available, then the compiler
- falls back to the normal behavior *)
+ let tag, nparams, arity = Renv.get_construct_info env c in
+ let nargs = Array.length args in
+ if nparams < nargs then (* got all parameters *)
let args = lambda_of_args env nparams args in
makeblock tag 0 arity args
- else
- let args = lambda_of_args env nparams args in
- (* spiwack: tries first to apply the run-time compilation
- behavior of the constructor, as in 2/ above *)
- (try
- (Retroknowledge.get_vm_constant_dynamic_info
- env.global_env.retroknowledge
- gr) args
- with Not_found ->
- if nparams <= nargs then (* got all parameters *)
- makeblock tag 0 arity args
- else (* still expecting some parameters *)
- makeblock tag (nparams - nargs) arity empty_args)
+ else makeblock tag (nparams - nargs) arity empty_args
| _ ->
- let f = lambda_of_constr env f in
- let args = lambda_of_args env 0 args in
- mkLapp f args
+ let f = lambda_of_constr env f in
+ let args = lambda_of_args env 0 args in
+ mkLapp f args
and lambda_of_args env start args =
let nargs = Array.length args in
@@ -822,43 +807,3 @@ let lambda_of_constr ~optimize genv c =
if !dump_lambda then
Feedback.msg_debug (pp_lam lam);
lam
-
-(** Retroknowledge, to be removed once we move to primitive machine integers *)
-let compile_structured_int31 fc args =
- if not fc then raise Not_found else
- Luint (UintVal
- (Uint31.of_int (Array.fold_left
- (fun temp_i -> fun t -> match kind t with
- | Construct ((_,d),_) -> 2*temp_i+d-1
- | _ -> raise NotClosed)
- 0 args)))
-
-let dynamic_int31_compilation fc args =
- if not fc then raise Not_found else
- Luint (UintDigits args)
-
-let d0 = Lint 0
-let d1 = Lint 1
-
-(* We are relying here on the tags of digits constructors *)
-let digits_from_uint i =
- let digits = Array.make 31 d0 in
- for k = 0 to 30 do
- if Int.equal ((Uint31.to_int i lsr k) land 1) 1 then
- digits.(30-k) <- d1
- done;
- digits
-
-let int31_escape_before_match fc t =
- if not fc then
- raise Not_found
- else
- match t with
- | Luint (UintVal i) ->
- let digits = digits_from_uint i in
- Lmakeblock (1, digits)
- | Luint (UintDigits args) ->
- Lmakeblock (1,args)
- | Luint (UintDecomp _) ->
- assert false
- | _ -> Luint (UintDecomp t)
diff --git a/kernel/clambda.mli b/kernel/clambda.mli
index 8ff10b4549..4d921fd45e 100644
--- a/kernel/clambda.mli
+++ b/kernel/clambda.mli
@@ -1,7 +1,37 @@
open Names
-open Cinstr
+open Constr
+open Vmvalues
open Environ
+type lambda =
+ | Lrel of Name.t * int
+ | Lvar of Id.t
+ | Levar of Evar.t * lambda array
+ | Lprod of lambda * lambda
+ | Llam of Name.t array * lambda
+ | Llet of Name.t * lambda * lambda
+ | Lapp of lambda * lambda array
+ | Lconst of pconstant
+ | Lprim of pconstant option * CPrimitives.t * lambda array
+ (* No check if None *)
+ | Lcase of case_info * reloc_table * lambda * lambda * lam_branches
+ | Lif of lambda * lambda * lambda
+ | Lfix of (int array * int) * fix_decl
+ | Lcofix of int * fix_decl
+ | Lint of int
+ | Lmakeblock of int * lambda array
+ | Luint of Uint63.t
+ | Lval of structured_values
+ | Lsort of Sorts.t
+ | Lind of pinductive
+ | Lproj of Projection.Repr.t * lambda
+
+and lam_branches =
+ { constant_branches : lambda array;
+ nonconstant_branches : (Name.t array * lambda) array }
+
+and fix_decl = Name.t array * lambda array * lambda array
+
exception TooLargeInductive of Pp.t
val lambda_of_constr : optimize:bool -> env -> Constr.t -> lambda
@@ -10,22 +40,5 @@ val decompose_Llam : lambda -> Name.t array * lambda
val get_alias : env -> Constant.t -> Constant.t
-val compile_prim : int -> Cbytecodes.instruction -> Constr.pconstant -> bool -> lambda array -> lambda
-
-(** spiwack: this function contains the information needed to perform
- the static compilation of int31 (trying and obtaining
- a 31-bit integer in processor representation at compile time) *)
-val compile_structured_int31 : bool -> Constr.t array -> lambda
-
-(** this function contains the information needed to perform
- the dynamic compilation of int31 (trying and obtaining a
- 31-bit integer in processor representation at runtime when
- it failed at compile time *)
-val dynamic_int31_compilation : bool -> lambda array -> lambda
-
-(*spiwack: compiling function to insert dynamic decompilation before
- matching integers (in case they are in processor representation) *)
-val int31_escape_before_match : bool -> lambda -> lambda
-
(** Dump the VM lambda code after compilation (for debugging purposes) *)
val dump_lambda : bool ref
diff --git a/kernel/constr.ml b/kernel/constr.ml
index d67d15b23b..c392494e95 100644
--- a/kernel/constr.ml
+++ b/kernel/constr.ml
@@ -101,6 +101,7 @@ type ('constr, 'types, 'sort, 'univs) kind_of_term =
| Fix of ('constr, 'types) pfixpoint
| CoFix of ('constr, 'types) pcofixpoint
| Proj of Projection.t * 'constr
+ | Int of Uint63.t
(* constr is the fixpoint of the previous type. Requires option
-rectypes of the Caml compiler to be set *)
type t = (t, t, Sorts.t, Instance.t) kind_of_term
@@ -233,6 +234,9 @@ let mkRef (gr,u) = let open GlobRef in match gr with
| ConstructRef c -> mkConstructU (c,u)
| VarRef x -> mkVar x
+(* Constructs a primitive integer *)
+let mkInt i = Int i
+
(************************************************************************)
(* kind_of_term = constructions as seen by the user *)
(************************************************************************)
@@ -438,7 +442,7 @@ let decompose_appvect c =
let fold f acc c = match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> acc
+ | Construct _ | Int _) -> acc
| Cast (c,_,t) -> f (f acc c) t
| Prod (_,t,c) -> f (f acc t) c
| Lambda (_,t,c) -> f (f acc t) c
@@ -458,7 +462,7 @@ let fold f acc c = match kind c with
let iter f c = match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> ()
+ | Construct _ | Int _) -> ()
| Cast (c,_,t) -> f c; f t
| Prod (_,t,c) -> f t; f c
| Lambda (_,t,c) -> f t; f c
@@ -478,7 +482,7 @@ let iter f c = match kind c with
let iter_with_binders g f n c = match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> ()
+ | Construct _ | Int _) -> ()
| Cast (c,_,t) -> f n c; f n t
| Prod (_,t,c) -> f n t; f (g n) c
| Lambda (_,t,c) -> f n t; f (g n) c
@@ -504,7 +508,7 @@ let iter_with_binders g f n c = match kind c with
let fold_constr_with_binders g f n acc c =
match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> acc
+ | Construct _ | Int _) -> acc
| Cast (c,_, t) -> f n (f n acc c) t
| Prod (_na,t,c) -> f (g n) (f n acc t) c
| Lambda (_na,t,c) -> f (g n) (f n acc t) c
@@ -600,7 +604,7 @@ let map_return_predicate_with_full_binders g f l ci p =
let map_gen userview f c = match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> c
+ | Construct _ | Int _) -> c
| Cast (b,k,t) ->
let b' = f b in
let t' = f t in
@@ -665,7 +669,7 @@ let map = map_gen false
let fold_map f accu c = match kind c with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> accu, c
+ | Construct _ | Int _) -> accu, c
| Cast (b,k,t) ->
let accu, b' = f accu b in
let accu, t' = f accu t in
@@ -725,7 +729,7 @@ let fold_map f accu c = match kind c with
let map_with_binders g f l c0 = match kind c0 with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> c0
+ | Construct _ | Int _) -> c0
| Cast (c, k, t) ->
let c' = f l c in
let t' = f l t in
@@ -802,7 +806,7 @@ let lift n = liftn n 1
let fold_with_full_binders g f n acc c =
let open Context.Rel.Declaration in
match kind c with
- | Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ -> acc
+ | Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _ | Int _ -> acc
| Cast (c,_, t) -> f n (f n acc c) t
| Prod (na,t,c) -> f (g (LocalAssum (na,t)) n) (f n acc t) c
| Lambda (na,t,c) -> f (g (LocalAssum (na,t)) n) (f n acc t) c
@@ -843,6 +847,7 @@ let compare_head_gen_leq_with kind1 kind2 leq_universes leq_sorts eq leq nargs t
| Rel n1, Rel n2 -> Int.equal n1 n2
| Meta m1, Meta m2 -> Int.equal m1 m2
| Var id1, Var id2 -> Id.equal id1 id2
+ | Int i1, Int i2 -> Uint63.equal i1 i2
| Sort s1, Sort s2 -> leq_sorts s1 s2
| Prod (_,t1,c1), Prod (_,t2,c2) -> eq 0 t1 t2 && leq 0 c1 c2
| Lambda (_,t1,c1), Lambda (_,t2,c2) -> eq 0 t1 t2 && eq 0 c1 c2
@@ -869,7 +874,7 @@ let compare_head_gen_leq_with kind1 kind2 leq_universes leq_sorts eq leq nargs t
Int.equal ln1 ln2 && Array.equal_norefl (eq 0) tl1 tl2 && Array.equal_norefl (eq 0) bl1 bl2
| (Rel _ | Meta _ | Var _ | Sort _ | Prod _ | Lambda _ | LetIn _ | App _
| Proj _ | Evar _ | Const _ | Ind _ | Construct _ | Case _ | Fix _
- | CoFix _), _ -> false
+ | CoFix _ | Int _), _ -> false
(* [compare_head_gen_leq u s eq leq c1 c2] compare [c1] and [c2] using [eq] to compare
the immediate subterms of [c1] of [c2] for conversion if needed, [leq] for cumulativity,
@@ -1044,6 +1049,8 @@ let constr_ord_int f t1 t2 =
ln1 ln2 tl1 tl2 bl1 bl2
| CoFix _, _ -> -1 | _, CoFix _ -> 1
| Proj (p1,c1), Proj (p2,c2) -> (Projection.compare =? f) p1 p2 c1 c2
+ | Proj _, _ -> -1 | _, Proj _ -> 1
+ | Int i1, Int i2 -> Uint63.compare i1 i2
let rec compare m n=
constr_ord_int compare m n
@@ -1127,9 +1134,10 @@ let hasheq t1 t2 =
&& array_eqeq lna1 lna2
&& array_eqeq tl1 tl2
&& array_eqeq bl1 bl2
+ | Int i1, Int i2 -> i1 == i2
| (Rel _ | Meta _ | Var _ | Sort _ | Cast _ | Prod _ | Lambda _ | LetIn _
| App _ | Proj _ | Evar _ | Const _ | Ind _ | Construct _ | Case _
- | Fix _ | CoFix _), _ -> false
+ | Fix _ | CoFix _ | Int _), _ -> false
(** Note that the following Make has the side effect of creating
once and for all the table we'll use for hash-consing all constr *)
@@ -1190,10 +1198,6 @@ let hashcons (sh_sort,sh_ci,sh_construct,sh_ind,sh_con,sh_na,sh_id) =
| Evar (e,l) ->
let l, hl = hash_term_array l in
(Evar (e,l), combinesmall 8 (combine (Evar.hash e) hl))
- | Proj (p,c) ->
- let c, hc = sh_rec c in
- let p' = Projection.hcons p in
- (Proj (p', c), combinesmall 17 (combine (Projection.SyntacticOrd.hash p') hc))
| Const (c,u) ->
let c' = sh_con c in
let u', hu = sh_instance u in
@@ -1232,6 +1236,13 @@ let hashcons (sh_sort,sh_ci,sh_construct,sh_ind,sh_con,sh_na,sh_id) =
(t, combinesmall 15 n)
| Rel n ->
(t, combinesmall 16 n)
+ | Proj (p,c) ->
+ let c, hc = sh_rec c in
+ let p' = Projection.hcons p in
+ (Proj (p', c), combinesmall 17 (combine (Projection.SyntacticOrd.hash p') hc))
+ | Int i ->
+ let (h,l) = Uint63.to_int2 i in
+ (t, combinesmall 18 (combine h l))
and sh_rec t =
let (y, h) = hash_term t in
@@ -1277,8 +1288,6 @@ let rec hash t =
| App (Cast(c, _, _),l) -> hash (mkApp (c,l))
| App (c,l) ->
combinesmall 7 (combine (hash_term_array l) (hash c))
- | Proj (p,c) ->
- combinesmall 17 (combine (Projection.hash p) (hash c))
| Evar (e,l) ->
combinesmall 8 (combine (Evar.hash e) (hash_term_array l))
| Const (c,u) ->
@@ -1295,6 +1304,9 @@ let rec hash t =
combinesmall 14 (combine (hash_term_array bl) (hash_term_array tl))
| Meta n -> combinesmall 15 n
| Rel n -> combinesmall 16 n
+ | Proj (p,c) ->
+ combinesmall 17 (combine (Projection.hash p) (hash c))
+ | Int i -> combinesmall 18 (Uint63.hash i)
and hash_term_array t =
Array.fold_left (fun acc t -> combine (hash t) acc) 0 t
@@ -1425,3 +1437,4 @@ let rec debug_print c =
Name.print na ++ str":" ++ debug_print ty ++
cut() ++ str":=" ++ debug_print bd) (Array.to_list fixl)) ++
str"}")
+ | Int i -> str"Int("++str (Uint63.to_string i) ++ str")"
diff --git a/kernel/constr.mli b/kernel/constr.mli
index f2cedcdabb..fdc3296a6a 100644
--- a/kernel/constr.mli
+++ b/kernel/constr.mli
@@ -72,6 +72,9 @@ val mkRel : int -> constr
(** Constructs a Variable *)
val mkVar : Id.t -> constr
+(** Constructs a machine integer *)
+val mkInt : Uint63.t -> constr
+
(** Constructs an patvar named "?n" *)
val mkMeta : metavariable -> constr
@@ -228,6 +231,7 @@ type ('constr, 'types, 'sort, 'univs) kind_of_term =
| Fix of ('constr, 'types) pfixpoint
| CoFix of ('constr, 'types) pcofixpoint
| Proj of Projection.t * 'constr
+ | Int of Uint63.t
(** User view of [constr]. For [App], it is ensured there is at
least one argument and the function is not itself an applicative
diff --git a/kernel/context.ml b/kernel/context.ml
index 3d98381fbb..1cc6e79485 100644
--- a/kernel/context.ml
+++ b/kernel/context.ml
@@ -134,6 +134,15 @@ struct
let ty' = f ty in
if v == v' && ty == ty' then decl else LocalDef (na, v', ty')
+ let map_constr_het f = function
+ | LocalAssum (na, ty) ->
+ let ty' = f ty in
+ LocalAssum (na, ty')
+ | LocalDef (na, v, ty) ->
+ let v' = f v in
+ let ty' = f ty in
+ LocalDef (na, v', ty')
+
(** Perform a given action on all terms in a given declaration. *)
let iter_constr f = function
| LocalAssum (_,ty) -> f ty
diff --git a/kernel/context.mli b/kernel/context.mli
index 2b0d36cb8c..8acae73680 100644
--- a/kernel/context.mli
+++ b/kernel/context.mli
@@ -78,6 +78,9 @@ sig
(** Map all terms in a given declaration. *)
val map_constr : ('c -> 'c) -> ('c, 'c) pt -> ('c, 'c) pt
+ (** Map all terms, with an heterogeneous function. *)
+ val map_constr_het : ('a -> 'b) -> ('a, 'a) pt -> ('b, 'b) pt
+
(** Perform a given action on all terms in a given declaration. *)
val iter_constr : ('c -> unit) -> ('c, 'c) pt -> unit
diff --git a/kernel/cooking.ml b/kernel/cooking.ml
index f4b4834d98..88586352f6 100644
--- a/kernel/cooking.ml
+++ b/kernel/cooking.ml
@@ -155,7 +155,7 @@ type recipe = { from : constant_body; info : Opaqueproof.cooking_info }
type inline = bool
type result = {
- cook_body : constant_def;
+ cook_body : constr Mod_subst.substituted constant_def;
cook_type : types;
cook_universes : constant_universes;
cook_private_univs : Univ.ContextSet.t option;
@@ -169,6 +169,7 @@ let on_body ml hy f = function
| OpaqueDef o ->
OpaqueDef (Opaqueproof.discharge_direct_opaque ~cook_constr:f
{ Opaqueproof.modlist = ml; abstract = hy } o)
+ | Primitive _ -> CErrors.anomaly (Pp.str "Primitives cannot be cooked")
let expmod_constr_subst cache modlist subst c =
let subst = Univ.make_instance_subst subst in
diff --git a/kernel/cooking.mli b/kernel/cooking.mli
index 7ff4b657d3..07c6f37fab 100644
--- a/kernel/cooking.mli
+++ b/kernel/cooking.mli
@@ -18,7 +18,7 @@ type recipe = { from : constant_body; info : Opaqueproof.cooking_info }
type inline = bool
type result = {
- cook_body : constant_def;
+ cook_body : constr Mod_subst.substituted constant_def;
cook_type : types;
cook_universes : constant_universes;
cook_private_univs : Univ.ContextSet.t option;
diff --git a/kernel/declarations.ml b/kernel/declarations.ml
index 016b63be09..1008492825 100644
--- a/kernel/declarations.ml
+++ b/kernel/declarations.ml
@@ -47,10 +47,11 @@ type inline = int option
transparent body, or an opaque one *)
(* Global declarations (i.e. constants) can be either: *)
-type constant_def =
+type 'a constant_def =
| Undef of inline (** a global assumption *)
- | Def of constr Mod_subst.substituted (** or a transparent global definition *)
+ | Def of 'a (** or a transparent global definition *)
| OpaqueDef of Opaqueproof.opaque (** or an opaque global definition *)
+ | Primitive of CPrimitives.t (** or a primitive operation *)
type constant_universes =
| Monomorphic_const of Univ.ContextSet.t
@@ -88,7 +89,7 @@ type typing_flags = {
* the OpaqueDef *)
type constant_body = {
const_hyps : Constr.named_context; (** New: younger hyp at top *)
- const_body : constant_def;
+ const_body : Constr.t Mod_subst.substituted constant_def;
const_type : types;
const_body_code : Cemitcodes.to_patch_substituted option;
const_universes : constant_universes;
diff --git a/kernel/declareops.ml b/kernel/declareops.ml
index 707c46048b..5686c4071d 100644
--- a/kernel/declareops.ml
+++ b/kernel/declareops.ml
@@ -56,8 +56,9 @@ let constant_is_polymorphic cb =
| Monomorphic_const _ -> false
| Polymorphic_const _ -> true
+
let constant_has_body cb = match cb.const_body with
- | Undef _ -> false
+ | Undef _ | Primitive _ -> false
| Def _ | OpaqueDef _ -> true
let constant_polymorphic_context cb =
@@ -67,7 +68,7 @@ let constant_polymorphic_context cb =
let is_opaque cb = match cb.const_body with
| OpaqueDef _ -> true
- | Undef _ | Def _ -> false
+ | Undef _ | Def _ | Primitive _ -> false
(** {7 Constant substitutions } *)
@@ -83,7 +84,7 @@ let subst_const_type sub arity =
(** No need here to check for physical equality after substitution,
at least for Def due to the delayed substitution [subst_constr_subst]. *)
let subst_const_def sub def = match def with
- | Undef _ -> def
+ | Undef _ | Primitive _ -> def
| Def c -> Def (subst_constr sub c)
| OpaqueDef o -> OpaqueDef (Opaqueproof.subst_opaque sub o)
@@ -119,6 +120,7 @@ let hcons_rel_context l = List.Smart.map hcons_rel_decl l
let hcons_const_def = function
| Undef inl -> Undef inl
+ | Primitive p -> Primitive p
| Def l_constr ->
let constr = force_constr l_constr in
Def (from_val (Constr.hcons constr))
diff --git a/kernel/dune b/kernel/dune
index 01abdb8f67..1f2d696a36 100644
--- a/kernel/dune
+++ b/kernel/dune
@@ -3,13 +3,23 @@
(synopsis "The Coq Kernel")
(public_name coq.kernel)
(wrapped false)
- (modules_without_implementation cinstr nativeinstr)
+ (modules (:standard \ uint63_x86 uint63_amd64 write_uint63))
(libraries lib byterun))
(rule
(targets copcodes.ml)
- (deps (:h-file byterun/coq_instruct.h) make-opcodes)
- (action (run ./make_opcodes.sh %{h-file} %{targets})))
+ (deps (:h-file byterun/coq_instruct.h) make-opcodes make_opcodes.sh)
+ (action (bash "./make_opcodes.sh %{h-file} %{targets}")))
+
+(executable
+ (name write_uint63)
+ (modules write_uint63)
+ (libraries unix))
+
+(rule
+ (targets uint63.ml)
+ (deps (:gen ./write_uint63.exe) uint63_x86.ml uint63_amd64.ml)
+ (action (run %{gen})))
(documentation
(package coq))
diff --git a/kernel/entries.ml b/kernel/entries.ml
index 58bb782f15..013327599d 100644
--- a/kernel/entries.ml
+++ b/kernel/entries.ml
@@ -87,9 +87,16 @@ type inline = int option (* inlining level, None for no inlining *)
type parameter_entry =
Constr.named_context option * types in_constant_universes_entry * inline
+type primitive_entry = {
+ prim_entry_type : types option;
+ prim_entry_univs : Univ.ContextSet.t; (* always monomorphic *)
+ prim_entry_content : CPrimitives.op_or_type;
+}
+
type 'a constant_entry =
| DefinitionEntry of 'a definition_entry
| ParameterEntry of parameter_entry
+ | PrimitiveEntry of primitive_entry
(** {6 Modules } *)
diff --git a/kernel/environ.ml b/kernel/environ.ml
index 77820a301e..886d6b1feb 100644
--- a/kernel/environ.ml
+++ b/kernel/environ.ml
@@ -119,7 +119,7 @@ let empty_env = {
env_universes = UGraph.initial_universes;
env_engagement = PredicativeSet };
env_typing_flags = Declareops.safe_flags Conv_oracle.empty;
- retroknowledge = Retroknowledge.initial_retroknowledge;
+ retroknowledge = Retroknowledge.empty;
indirect_pterms = Opaqueproof.empty_opaquetab }
@@ -222,6 +222,10 @@ let lookup_constant kn env =
let lookup_mind kn env =
fst (Mindmap_env.find kn env.env_globals.env_inductives)
+let mind_context env mind =
+ let mib = lookup_mind mind env in
+ Declareops.inductive_polymorphic_context mib
+
let lookup_mind_key kn env =
Mindmap_env.find kn env.env_globals.env_inductives
@@ -450,7 +454,10 @@ let constant_type env (kn,u) =
let csts = Univ.AUContext.instantiate u uctx in
(subst_instance_constr u cb.const_type, csts)
-type const_evaluation_result = NoBody | Opaque
+type const_evaluation_result =
+ | NoBody
+ | Opaque
+ | IsPrimitive of CPrimitives.t
exception NotEvaluableConst of const_evaluation_result
@@ -461,14 +468,14 @@ let constant_value_and_type env (kn, u) =
let b' = match cb.const_body with
| Def l_body -> Some (subst_instance_constr u (Mod_subst.force_constr l_body))
| OpaqueDef _ -> None
- | Undef _ -> None
+ | Undef _ | Primitive _ -> None
in
b', subst_instance_constr u cb.const_type, cst
let body_of_constant_body env cb =
let otab = opaque_tables env in
match cb.const_body with
- | Undef _ ->
+ | Undef _ | Primitive _ ->
None
| Def c ->
Some (Mod_subst.force_constr c, Declareops.constant_polymorphic_context cb)
@@ -492,6 +499,7 @@ let constant_value_in env (kn,u) =
subst_instance_constr u b
| OpaqueDef _ -> raise (NotEvaluableConst Opaque)
| Undef _ -> raise (NotEvaluableConst NoBody)
+ | Primitive p -> raise (NotEvaluableConst (IsPrimitive p))
let constant_opt_value_in env cst =
try Some (constant_value_in env cst)
@@ -503,7 +511,13 @@ let evaluable_constant kn env =
match cb.const_body with
| Def _ -> true
| OpaqueDef _ -> false
- | Undef _ -> false
+ | Undef _ | Primitive _ -> false
+
+let is_primitive env c =
+ let cb = lookup_constant c env in
+ match cb.Declarations.const_body with
+ | Declarations.Primitive _ -> true
+ | _ -> false
let polymorphic_constant cst env =
Declareops.constant_is_polymorphic (lookup_constant cst env)
@@ -743,29 +757,4 @@ let is_type_in_type env r =
| IndRef ind -> type_in_type_ind ind env
| ConstructRef cstr -> type_in_type_ind (inductive_of_constructor cstr) env
-(*spiwack: the following functions assemble the pieces of the retroknowledge
- note that the "consistent" register function is available in the module
- Safetyping, Environ only synchronizes the proactive and the reactive parts*)
-
-open Retroknowledge
-
-(* lifting of the "get" functions works also for "mem"*)
-let retroknowledge f env =
- f env.retroknowledge
-
-let registered env field =
- retroknowledge mem env field
-
-let register_one env field entry =
- { env with retroknowledge = Retroknowledge.add_field env.retroknowledge field entry }
-
-(* [register env field entry] may register several fields when needed *)
-let register env field gr =
- match field with
- | KInt31 Int31Type ->
- let i31c = match gr with
- | GlobRef.IndRef i31t -> GlobRef.ConstructRef (i31t, 1)
- | _ -> anomaly ~label:"Environ.register" (Pp.str "should be an inductive type.")
- in
- register_one (register_one env (KInt31 Int31Constructor) i31c) field gr
- | field -> register_one env field gr
+let set_retroknowledge env r = { env with retroknowledge = r }
diff --git a/kernel/environ.mli b/kernel/environ.mli
index 6d4d3b282b..a9e0717559 100644
--- a/kernel/environ.mli
+++ b/kernel/environ.mli
@@ -195,11 +195,15 @@ val type_in_type_constant : Constant.t -> env -> bool
(** {6 ... } *)
(** [constant_value env c] raises [NotEvaluableConst Opaque] if
- [c] is opaque and [NotEvaluableConst NoBody] if it has no
- body and [NotEvaluableConst IsProj] if [c] is a projection
+ [c] is opaque, [NotEvaluableConst NoBody] if it has no
+ body, [NotEvaluableConst IsProj] if [c] is a projection,
+ [NotEvaluableConst (IsPrimitive p)] if [c] is primitive [p]
and [Not_found] if it does not exist in [env] *)
-type const_evaluation_result = NoBody | Opaque
+type const_evaluation_result =
+ | NoBody
+ | Opaque
+ | IsPrimitive of CPrimitives.t
exception NotEvaluableConst of const_evaluation_result
val constant_type : env -> Constant.t puniverses -> types constrained
@@ -223,6 +227,8 @@ val constant_value_in : env -> Constant.t puniverses -> constr
val constant_type_in : env -> Constant.t puniverses -> types
val constant_opt_value_in : env -> Constant.t puniverses -> constr option
+val is_primitive : env -> Constant.t -> bool
+
(** {6 Primitive projections} *)
(** Checks that the number of parameters is correct. *)
@@ -240,6 +246,10 @@ val add_mind : MutInd.t -> mutual_inductive_body -> env -> env
raises [Not_found] if the required path is not found *)
val lookup_mind : MutInd.t -> env -> mutual_inductive_body
+(** The universe context associated to the inductive, empty if not
+ polymorphic *)
+val mind_context : env -> MutInd.t -> Univ.AUContext.t
+
(** New-style polymorphism *)
val polymorphic_ind : inductive -> env -> bool
val polymorphic_pind : pinductive -> env -> bool
@@ -334,13 +344,8 @@ val is_polymorphic : env -> Names.GlobRef.t -> bool
val is_template_polymorphic : env -> GlobRef.t -> bool
val is_type_in_type : env -> GlobRef.t -> bool
-open Retroknowledge
-(** functions manipulating the retroknowledge
- @author spiwack *)
-
-val registered : env -> field -> bool
-
-val register : env -> field -> GlobRef.t -> env
-
(** Native compiler *)
val no_link_info : link_info
+
+(** Primitives *)
+val set_retroknowledge : env -> Retroknowledge.retroknowledge -> env
diff --git a/kernel/indtypes.ml b/kernel/indtypes.ml
index 9bb848c6a4..674d7a2a91 100644
--- a/kernel/indtypes.ml
+++ b/kernel/indtypes.ml
@@ -536,9 +536,13 @@ let build_inductive env names prv univs paramsctxt kn isrecord isfinite inds nmr
let record_info = match isrecord with
| Some (Some rid) ->
let is_record pkt =
- List.exists (Sorts.family_equal Sorts.InType) pkt.mind_kelim
- && Array.length pkt.mind_consnames == 1
- && pkt.mind_consnrealargs.(0) > 0
+ if Array.length pkt.mind_consnames != 1 then
+ user_err ~hdr:"build_inductive"
+ Pp.(str "Primitive records must have exactly one constructor.")
+ else if pkt.mind_consnrealargs.(0) = 0 then
+ user_err ~hdr:"build_inductive"
+ Pp.(str "Primitive records must have at least one constructor argument.")
+ else List.exists (Sorts.family_equal Sorts.InType) pkt.mind_kelim
in
(** The elimination criterion ensures that all projections can be defined. *)
if Array.for_all is_record packets then
diff --git a/kernel/inductive.ml b/kernel/inductive.ml
index 05c5c0e821..c62d0e7ded 100644
--- a/kernel/inductive.ml
+++ b/kernel/inductive.ml
@@ -804,7 +804,7 @@ let rec subterm_specif renv stack t =
| Not_subterm -> Not_subterm)
| Var _ | Sort _ | Cast _ | Prod _ | LetIn _ | App _ | Const _ | Ind _
- | Construct _ | CoFix _ -> Not_subterm
+ | Construct _ | CoFix _ | Int _ -> Not_subterm
(* Other terms are not subterms *)
@@ -1008,7 +1008,7 @@ let check_one_fix renv recpos trees def =
check_rec_call renv stack (Term.applist(c,l))
end
- | Sort _ ->
+ | Sort _ | Int _ ->
assert (List.is_empty l)
(* l is not checked because it is considered as the meta's context *)
@@ -1194,7 +1194,8 @@ let check_one_cofix env nbfix def deftype =
| Evar _ ->
List.iter (check_rec_call env alreadygrd n tree vlra) args
| Rel _ | Var _ | Sort _ | Cast _ | Prod _ | LetIn _ | App _ | Const _
- | Ind _ | Fix _ | Proj _ -> raise (CoFixGuardError (env,NotGuardedForm t)) in
+ | Ind _ | Fix _ | Proj _ | Int _ ->
+ raise (CoFixGuardError (env,NotGuardedForm t)) in
let ((mind, _),_) = codomain_is_coind env deftype in
let vlra = lookup_subterms env mind in
diff --git a/kernel/kernel.mllib b/kernel/kernel.mllib
index 0b10e788b6..5108744bde 100644
--- a/kernel/kernel.mllib
+++ b/kernel/kernel.mllib
@@ -1,6 +1,7 @@
Names
TransparentState
-Uint31
+Uint63
+CPrimitives
Univ
UGraph
Esubst
@@ -19,11 +20,11 @@ Opaqueproof
Declarations
Entries
Nativevalues
-CPrimitives
Declareops
Retroknowledge
Conv_oracle
Environ
+Primred
CClosure
Reduction
Clambda
diff --git a/kernel/mod_subst.ml b/kernel/mod_subst.ml
index 52fb39e1d0..cd675653cb 100644
--- a/kernel/mod_subst.ml
+++ b/kernel/mod_subst.ml
@@ -330,6 +330,19 @@ let subst_proj_repr sub p =
let subst_proj sub p =
Projection.map (subst_mind sub) p
+let subst_retro_action subst action =
+ let open Retroknowledge in
+ match action with
+ | Register_ind(prim,ind) ->
+ let ind' = subst_ind subst ind in
+ if ind == ind' then action else Register_ind(prim, ind')
+ | Register_type(prim,c) ->
+ let c' = subst_constant subst c in
+ if c == c' then action else Register_type(prim, c')
+ | Register_inline(c) ->
+ let c' = subst_constant subst c in
+ if c == c' then action else Register_inline(c')
+
(* Here the semantics is completely unclear.
What does "Hint Unfold t" means when "t" is a parameter?
Does the user mean "Unfold X.t" or does she mean "Unfold y"
diff --git a/kernel/mod_subst.mli b/kernel/mod_subst.mli
index ea391b3de7..8ab3d04402 100644
--- a/kernel/mod_subst.mli
+++ b/kernel/mod_subst.mli
@@ -144,6 +144,8 @@ val subst_constant :
val subst_proj_repr : substitution -> Projection.Repr.t -> Projection.Repr.t
val subst_proj : substitution -> Projection.t -> Projection.t
+val subst_retro_action : substitution -> Retroknowledge.action -> Retroknowledge.action
+
(** Here the semantics is completely unclear.
What does "Hint Unfold t" means when "t" is a parameter?
Does the user mean "Unfold X.t" or does she mean "Unfold y"
diff --git a/kernel/mod_typing.ml b/kernel/mod_typing.ml
index d63dc057b4..f68dd158c2 100644
--- a/kernel/mod_typing.ml
+++ b/kernel/mod_typing.ml
@@ -68,12 +68,12 @@ let rec check_with_def env struc (idl,(c,ctx)) mp equiv =
if List.is_empty idl then
(* Toplevel definition *)
let cb = match spec with
- | SFBconst cb -> cb
- | _ -> error_not_a_constant lab
+ | SFBconst cb -> cb
+ | _ -> error_not_a_constant lab
in
(* In the spirit of subtyping.check_constant, we accept
any implementations of parameters and opaques terms,
- as long as they have the right type *)
+ as long as they have the right type *)
let c', univs, ctx' =
match cb.const_universes, ctx with
| Monomorphic_const _, None ->
@@ -87,6 +87,8 @@ let rec check_with_def env struc (idl,(c,ctx)) mp equiv =
| Def cs ->
let c' = Mod_subst.force_constr cs in
c, Reduction.infer_conv env' (Environ.universes env') c c'
+ | Primitive _ ->
+ error_incorrect_with_constraint lab
in
c', Monomorphic_const Univ.ContextSet.empty, cst
| Polymorphic_const uctx, Some ctx ->
@@ -95,52 +97,54 @@ let rec check_with_def env struc (idl,(c,ctx)) mp equiv =
error_incorrect_with_constraint lab
in
(** Terms are compared in a context with De Bruijn universe indices *)
- let env' = Environ.push_context ~strict:false (Univ.AUContext.repr uctx) env in
- let cst = match cb.const_body with
- | Undef _ | OpaqueDef _ ->
- let j = Typeops.infer env' c in
- let typ = cb.const_type in
- let cst' = Reduction.infer_conv_leq env' (Environ.universes env')
- j.uj_type typ in
- cst'
- | Def cs ->
- let c' = Mod_subst.force_constr cs in
- let cst' = Reduction.infer_conv env' (Environ.universes env') c c' in
- cst'
- in
- if not (Univ.Constraint.is_empty cst) then
- error_incorrect_with_constraint lab;
- c, Polymorphic_const ctx, Univ.Constraint.empty
+ let env' = Environ.push_context ~strict:false (Univ.AUContext.repr uctx) env in
+ let cst = match cb.const_body with
+ | Undef _ | OpaqueDef _ ->
+ let j = Typeops.infer env' c in
+ let typ = cb.const_type in
+ let cst' = Reduction.infer_conv_leq env' (Environ.universes env')
+ j.uj_type typ in
+ cst'
+ | Def cs ->
+ let c' = Mod_subst.force_constr cs in
+ let cst' = Reduction.infer_conv env' (Environ.universes env') c c' in
+ cst'
+ | Primitive _ ->
+ error_incorrect_with_constraint lab
+ in
+ if not (Univ.Constraint.is_empty cst) then
+ error_incorrect_with_constraint lab;
+ c, Polymorphic_const ctx, Univ.Constraint.empty
| _ -> error_incorrect_with_constraint lab
in
let def = Def (Mod_subst.from_val c') in
-(* let ctx' = Univ.UContext.make (newus, cst) in *)
+ (* let ctx' = Univ.UContext.make (newus, cst) in *)
let cb' =
- { cb with
- const_body = def;
+ { cb with
+ const_body = def;
const_universes = univs ;
- const_body_code = Option.map Cemitcodes.from_val
- (Cbytegen.compile_constant_body ~fail_on_error:false env' cb.const_universes def) }
+ const_body_code = Option.map Cemitcodes.from_val
+ (Cbytegen.compile_constant_body ~fail_on_error:false env' cb.const_universes def) }
in
before@(lab,SFBconst(cb'))::after, c', ctx'
else
(* Definition inside a sub-module *)
let mb = match spec with
- | SFBmodule mb -> mb
- | _ -> error_not_a_module (Label.to_string lab)
+ | SFBmodule mb -> mb
+ | _ -> error_not_a_module (Label.to_string lab)
in
begin match mb.mod_expr with
- | Abstract ->
- let struc = Modops.destr_nofunctor mb.mod_type in
- let struc',c',cst =
- check_with_def env' struc (idl,(c,ctx)) (MPdot(mp,lab)) mb.mod_delta
- in
- let mb' = { mb with
- mod_type = NoFunctor struc';
- mod_type_alg = None }
- in
- before@(lab,SFBmodule mb')::after, c', cst
- | _ -> error_generative_module_expected lab
+ | Abstract ->
+ let struc = Modops.destr_nofunctor mb.mod_type in
+ let struc',c',cst =
+ check_with_def env' struc (idl,(c,ctx)) (MPdot(mp,lab)) mb.mod_delta
+ in
+ let mb' = { mb with
+ mod_type = NoFunctor struc';
+ mod_type_alg = None }
+ in
+ before@(lab,SFBmodule mb')::after, c', cst
+ | _ -> error_generative_module_expected lab
end
with
| Not_found -> error_no_such_label lab
diff --git a/kernel/modops.ml b/kernel/modops.ml
index 97ac3cdebb..1dc8eec0da 100644
--- a/kernel/modops.ml
+++ b/kernel/modops.ml
@@ -197,9 +197,18 @@ let rec subst_structure sub do_delta sign =
in
List.Smart.map subst_body sign
+and subst_retro : type a. Mod_subst.substitution -> a module_retroknowledge -> a module_retroknowledge =
+ fun subst retro ->
+ match retro with
+ | ModTypeRK as r -> r
+ | ModBodyRK l as r ->
+ let l' = List.Smart.map (subst_retro_action subst) l in
+ if l == l' then r else ModBodyRK l
+
and subst_body : 'a. _ -> _ -> (_ -> 'a -> 'a) -> _ -> 'a generic_module_body -> 'a generic_module_body =
fun is_mod sub subst_impl do_delta mb ->
- let { mod_mp=mp; mod_expr=me; mod_type=ty; mod_type_alg=aty; _ } = mb in
+ let { mod_mp=mp; mod_expr=me; mod_type=ty; mod_type_alg=aty;
+ mod_retroknowledge=retro; _ } = mb in
let mp' = subst_mp sub mp in
let sub =
if ModPath.equal mp mp' then sub
@@ -209,8 +218,10 @@ and subst_body : 'a. _ -> _ -> (_ -> 'a -> 'a) -> _ -> 'a generic_module_body ->
let ty' = subst_signature sub do_delta ty in
let me' = subst_impl sub me in
let aty' = Option.Smart.map (subst_expression sub id_delta) aty in
+ let retro' = subst_retro sub retro in
let delta' = do_delta mb.mod_delta sub in
- if mp==mp' && me==me' && ty==ty' && aty==aty' && delta'==mb.mod_delta
+ if mp==mp' && me==me' && ty==ty' && aty==aty'
+ && retro==retro' && delta'==mb.mod_delta
then mb
else
{ mb with
@@ -218,7 +229,9 @@ and subst_body : 'a. _ -> _ -> (_ -> 'a -> 'a) -> _ -> 'a generic_module_body ->
mod_expr = me';
mod_type = ty';
mod_type_alg = aty';
- mod_delta = delta' }
+ mod_retroknowledge = retro';
+ mod_delta = delta';
+ }
and subst_module sub do_delta mb =
subst_body true sub subst_impl do_delta mb
@@ -259,32 +272,12 @@ let do_delta_dom_codom reso sub = subst_dom_codom_delta_resolver sub reso
let subst_signature subst = subst_signature subst do_delta_codom
let subst_structure subst = subst_structure subst do_delta_codom
-(** {6 Retroknowledge } *)
-
-(* spiwack: here comes the function which takes care of importing
- the retroknowledge declared in the library *)
-(* lclrk : retroknowledge_action list, rkaction : retroknowledge action *)
-let add_retroknowledge =
- let perform rkaction env = match rkaction with
- | Retroknowledge.RKRegister (f, ((GlobRef.ConstRef _ | GlobRef.IndRef _) as e)) ->
- Environ.register env f e
- | _ ->
- CErrors.anomaly ~label:"Modops.add_retroknowledge"
- (Pp.str "had to import an unsupported kind of term.")
- in
- fun (ModBodyRK lclrk) env ->
- (* The order of the declaration matters, for instance (and it's at the
- time this comment is being written, the only relevent instance) the
- int31 type registration absolutely needs int31 bits to be registered.
- Since the local_retroknowledge is stored in reverse order (each new
- registration is added at the top of the list) we need a fold_right
- for things to go right (the pun is not intented). So we lose
- tail recursivity, but the world will have exploded before any module
- imports 10 000 retroknowledge registration.*)
- List.fold_right perform lclrk env
-
(** {6 Adding a module in the environment } *)
+let add_retroknowledge r env =
+ match r with
+ | ModBodyRK l -> List.fold_left Primred.add_retroknowledge env l
+
let rec add_structure mp sign resolver linkinfo env =
let add_one env (l,elem) = match elem with
|SFBconst cb ->
@@ -399,7 +392,7 @@ let inline_delta_resolver env inl mp mbid mtb delta =
let constant = lookup_constant con env in
let l = make_inline delta r in
match constant.const_body with
- | Undef _ | OpaqueDef _ -> l
+ | Undef _ | OpaqueDef _ | Primitive _ -> l
| Def body ->
let constr = Mod_subst.force_constr body in
let ctx = Declareops.constant_polymorphic_context constant in
diff --git a/kernel/modops.mli b/kernel/modops.mli
index 0acd09fb12..bb97f0171e 100644
--- a/kernel/modops.mli
+++ b/kernel/modops.mli
@@ -57,6 +57,8 @@ val add_linked_module : module_body -> link_info -> env -> env
(** same, for a module type *)
val add_module_type : ModPath.t -> module_type_body -> env -> env
+val add_retroknowledge : module_implementation module_retroknowledge -> env -> env
+
(** {6 Strengthening } *)
val strengthen : module_type_body -> ModPath.t -> module_type_body
diff --git a/kernel/nativecode.ml b/kernel/nativecode.ml
index 482a2f3a3c..c32bdb85d6 100644
--- a/kernel/nativecode.ml
+++ b/kernel/nativecode.ml
@@ -14,7 +14,6 @@ open Constr
open Declarations
open Util
open Nativevalues
-open Nativeinstr
open Nativelambda
open Environ
@@ -286,8 +285,6 @@ type primitive =
| Mk_int
| Mk_bool
| Val_to_int
- | Mk_I31_accu
- | Decomp_uint
| Mk_meta
| Mk_evar
| MLand
@@ -305,7 +302,7 @@ type primitive =
| MLmagic
| MLarrayget
| Mk_empty_instance
- | Coq_primitive of CPrimitives.t * (prefix * Constant.t) option
+ | Coq_primitive of CPrimitives.t * (prefix * pconstant) option
let eq_primitive p1 p2 =
match p1, p2 with
@@ -351,29 +348,27 @@ let primitive_hash = function
| Mk_int -> 16
| Mk_bool -> 17
| Val_to_int -> 18
- | Mk_I31_accu -> 19
- | Decomp_uint -> 20
- | Mk_meta -> 21
- | Mk_evar -> 22
- | MLand -> 23
- | MLle -> 24
- | MLlt -> 25
- | MLinteq -> 26
- | MLlsl -> 27
- | MLlsr -> 28
- | MLland -> 29
- | MLlor -> 30
- | MLlxor -> 31
- | MLadd -> 32
- | MLsub -> 33
- | MLmul -> 34
- | MLmagic -> 35
- | Coq_primitive (prim, None) -> combinesmall 36 (CPrimitives.hash prim)
- | Coq_primitive (prim, Some (prefix,kn)) ->
- combinesmall 37 (combine3 (String.hash prefix) (Constant.hash kn) (CPrimitives.hash prim))
- | Mk_proj -> 38
- | MLarrayget -> 39
- | Mk_empty_instance -> 40
+ | Mk_meta -> 19
+ | Mk_evar -> 20
+ | MLand -> 21
+ | MLle -> 22
+ | MLlt -> 23
+ | MLinteq -> 24
+ | MLlsl -> 25
+ | MLlsr -> 26
+ | MLland -> 27
+ | MLlor -> 28
+ | MLlxor -> 29
+ | MLadd -> 30
+ | MLsub -> 31
+ | MLmul -> 32
+ | MLmagic -> 33
+ | Coq_primitive (prim, None) -> combinesmall 34 (CPrimitives.hash prim)
+ | Coq_primitive (prim, Some (prefix,(kn,_))) ->
+ combinesmall 35 (combine3 (String.hash prefix) (Constant.hash kn) (CPrimitives.hash prim))
+ | Mk_proj -> 36
+ | MLarrayget -> 37
+ | Mk_empty_instance -> 38
type mllambda =
| MLlocal of lname
@@ -389,7 +384,7 @@ type mllambda =
| MLconstruct of string * constructor * mllambda array
(* prefix, constructor name, arguments *)
| MLint of int
- | MLuint of Uint31.t
+ | MLuint of Uint63.t
| MLsetref of string * mllambda
| MLsequence of mllambda * mllambda
| MLarray of mllambda array
@@ -455,7 +450,7 @@ let rec eq_mllambda gn1 gn2 n env1 env2 t1 t2 =
| MLint i1, MLint i2 ->
Int.equal i1 i2
| MLuint i1, MLuint i2 ->
- Uint31.equal i1 i2
+ Uint63.equal i1 i2
| MLsetref (id1, ml1), MLsetref (id2, ml2) ->
String.equal id1 id2 &&
eq_mllambda gn1 gn2 n env1 env2 ml1 ml2
@@ -534,7 +529,7 @@ let rec hash_mllambda gn n env t =
| MLint i ->
combinesmall 11 i
| MLuint i ->
- combinesmall 12 (Uint31.to_int i)
+ combinesmall 12 (Uint63.hash i)
| MLsetref (id, ml) ->
let hid = String.hash id in
let hml = hash_mllambda gn n env ml in
@@ -947,9 +942,10 @@ let merge_branches t =
Array.iter (fun (c,args,body) -> insert (c,args) body newt) t;
Array.of_list (to_list newt)
+let app_prim p args = MLapp(MLprimitive p, args)
-type prim_aux =
- | PAprim of string * Constant.t * CPrimitives.t * prim_aux array
+type prim_aux =
+ | PAprim of string * pconstant * CPrimitives.t * prim_aux array
| PAml of mllambda
let add_check cond args =
@@ -962,97 +958,67 @@ let add_check cond args =
| _ -> cond
in
Array.fold_left aux cond args
-
+
let extract_prim ml_of l =
let decl = ref [] in
let cond = ref [] in
- let rec aux l =
+ let rec aux l =
match l with
| Lprim(prefix,kn,p,args) ->
- let args = Array.map aux args in
- cond := add_check !cond args;
- PAprim(prefix,kn,p,args)
+ let args = Array.map aux args in
+ cond := add_check !cond args;
+ PAprim(prefix,kn,p,args)
| Lrel _ | Lvar _ | Luint _ | Lval _ | Lconst _ -> PAml (ml_of l)
- | _ ->
- let x = fresh_lname Anonymous in
- decl := (x,ml_of l)::!decl;
- PAml (MLlocal x) in
+ | _ ->
+ let x = fresh_lname Anonymous in
+ decl := (x,ml_of l)::!decl;
+ PAml (MLlocal x) in
let res = aux l in
(!decl, !cond, res)
-let app_prim p args = MLapp(MLprimitive p, args)
-
-let to_int v =
+let cast_to_int v =
match v with
- | MLapp(MLprimitive Mk_uint, t) ->
- begin match t.(0) with
- | MLuint i -> MLint (Uint31.to_int i)
- | _ -> MLapp(MLprimitive Val_to_int, [|v|])
- end
- | MLapp(MLprimitive Mk_int, t) -> t.(0)
- | _ -> MLapp(MLprimitive Val_to_int, [|v|])
-
-let of_int v =
- match v with
- | MLapp(MLprimitive Val_to_int, t) -> t.(0)
- | _ -> MLapp(MLprimitive Mk_int,[|v|])
+ | MLint _ -> v
+ | _ -> MLapp(MLprimitive Val_to_int, [|v|])
let compile_prim decl cond paux =
-(*
- let args_to_int args =
- for i = 0 to Array.length args - 1 do
- args.(i) <- to_int args.(i)
- done;
- args in
- *)
+
let rec opt_prim_aux paux =
match paux with
| PAprim(_prefix, _kn, op, args) ->
- let args = Array.map opt_prim_aux args in
- app_prim (Coq_primitive(op,None)) args
-(*
- TODO: check if this inlining was useful
- begin match op with
- | Int31lt ->
- if Sys.word_size = 64 then
- app_prim Mk_bool [|(app_prim MLlt (args_to_int args))|]
- else app_prim (Coq_primitive (CPrimitives.Int31lt,None)) args
- | Int31le ->
- if Sys.word_size = 64 then
- app_prim Mk_bool [|(app_prim MLle (args_to_int args))|]
- else app_prim (Coq_primitive (CPrimitives.Int31le, None)) args
- | Int31lsl -> of_int (mk_lsl (args_to_int args))
- | Int31lsr -> of_int (mk_lsr (args_to_int args))
- | Int31land -> of_int (mk_land (args_to_int args))
- | Int31lor -> of_int (mk_lor (args_to_int args))
- | Int31lxor -> of_int (mk_lxor (args_to_int args))
- | Int31add -> of_int (mk_add (args_to_int args))
- | Int31sub -> of_int (mk_sub (args_to_int args))
- | Int31mul -> of_int (mk_mul (args_to_int args))
- | _ -> app_prim (Coq_primitive(op,None)) args
- end *)
- | PAml ml -> ml
- and naive_prim_aux paux =
+ let args = Array.map opt_prim_aux args in
+ app_prim (Coq_primitive(op,None)) args
+ | PAml ml -> ml
+
+ and naive_prim_aux paux =
match paux with
| PAprim(prefix, kn, op, args) ->
- app_prim (Coq_primitive(op, Some (prefix, kn))) (Array.map naive_prim_aux args)
- | PAml ml -> ml in
+ app_prim (Coq_primitive(op, Some (prefix,kn))) (Array.map naive_prim_aux args)
+ | PAml ml -> ml
+ in
- let compile_cond cond paux =
+ let compile_cond cond paux =
match cond with
- | [] -> opt_prim_aux paux
+ | [] -> opt_prim_aux paux
| [c1] ->
- MLif(app_prim Is_int [|c1|], opt_prim_aux paux, naive_prim_aux paux)
+ MLif(app_prim Is_int [|c1|], opt_prim_aux paux, naive_prim_aux paux)
| c1::cond ->
- let cond =
- List.fold_left
- (fun ml c -> app_prim MLland [| ml; to_int c|])
- (app_prim MLland [|to_int c1; MLint 0 |]) cond in
- let cond = app_prim MLmagic [|cond|] in
- MLif(cond, naive_prim_aux paux, opt_prim_aux paux) in
+ let cond =
+ List.fold_left
+ (fun ml c -> app_prim MLland [| ml; cast_to_int c|])
+ (app_prim MLland [| cast_to_int c1; MLint 0 |]) cond in
+ let cond = app_prim MLmagic [|cond|] in
+ MLif(cond, naive_prim_aux paux, opt_prim_aux paux) in
+
let add_decl decl body =
List.fold_left (fun body (x,d) -> MLlet(x,d,body)) body decl in
- add_decl decl (compile_cond cond paux)
+
+ (* The optimizations done for checking if integer values are closed are valid
+ only on 64-bit architectures. So on 32-bit architectures, we fall back to less optimized checks. *)
+ if max_int = 1073741823 (* 32-bits *) then
+ add_decl decl (naive_prim_aux paux)
+ else
+ add_decl decl (compile_cond cond paux)
let ml_of_instance instance u =
let ml_of_level l =
@@ -1089,6 +1055,11 @@ let ml_of_instance instance u =
| Llam(ids,body) ->
let lnames,env = push_rels env ids in
MLlam(lnames, ml_of_lam env l body)
+ | Lrec(id,body) ->
+ let ids,body = decompose_Llam body in
+ let lname, env = push_rel env id in
+ let lnames, env = push_rels env ids in
+ MLletrec([|lname, lnames, ml_of_lam env l body|], MLlocal lname)
| Llet(id,def,body) ->
let def = ml_of_lam env l def in
let lname, env = push_rel env id in
@@ -1101,8 +1072,8 @@ let ml_of_instance instance u =
mkMLapp (MLglobal(Gconstant (prefix, c))) args
| Lproj (prefix, ind, i) -> MLglobal(Gproj (prefix, ind, i))
| Lprim _ ->
- let decl,cond,paux = extract_prim (ml_of_lam env l) t in
- compile_prim decl cond paux
+ let decl,cond,paux = extract_prim (ml_of_lam env l) t in
+ compile_prim decl cond paux
| Lcase (annot,p,a,bs) ->
(* let predicate_uid fv_pred = compilation of p
let rec case_uid fv a_uid =
@@ -1311,18 +1282,7 @@ let ml_of_instance instance u =
| Lconstruct (prefix, (cn,u)) ->
let uargs = ml_of_instance env.env_univ u in
mkMLapp (MLglobal (Gconstruct (prefix, cn))) uargs
- | Luint v ->
- (match v with
- | UintVal i -> MLapp(MLprimitive Mk_uint, [|MLuint i|])
- | UintDigits (prefix,cn,ds) ->
- let c = MLglobal (Gconstruct (prefix, cn)) in
- let ds = Array.map (ml_of_lam env l) ds in
- let i31 = MLapp (MLprimitive Mk_I31_accu, [|c|]) in
- MLapp(i31, ds)
- | UintDecomp (prefix,cn,t) ->
- let c = MLglobal (Gconstruct (prefix, cn)) in
- let t = ml_of_lam env l t in
- MLapp (MLprimitive Decomp_uint, [|c;t|]))
+ | Luint i -> MLapp(MLprimitive Mk_uint, [|MLuint i|])
| Lval v ->
let i = push_symbol (SymbValue v) in get_value_code i
| Lsort s ->
@@ -1646,7 +1606,7 @@ let pp_mllam fmt l =
Format.fprintf fmt "@[(Obj.magic (%s%a) : Nativevalues.t)@]"
(string_of_construct prefix c) pp_cargs args
| MLint i -> pp_int fmt i
- | MLuint i -> Format.fprintf fmt "(Uint31.of_int %a)" pp_int (Uint31.to_int i)
+ | MLuint i -> Format.fprintf fmt "(%s)" (Uint63.compile i)
| MLsetref (s, body) ->
Format.fprintf fmt "@[%s@ :=@\n %a@]" s pp_mllam body
| MLsequence(l1,l2) ->
@@ -1766,8 +1726,6 @@ let pp_mllam fmt l =
| Mk_int -> Format.fprintf fmt "mk_int"
| Mk_bool -> Format.fprintf fmt "mk_bool"
| Val_to_int -> Format.fprintf fmt "val_to_int"
- | Mk_I31_accu -> Format.fprintf fmt "mk_I31_accu"
- | Decomp_uint -> Format.fprintf fmt "decomp_uint"
| Mk_meta -> Format.fprintf fmt "mk_meta_accu"
| Mk_evar -> Format.fprintf fmt "mk_evar_accu"
| MLand -> Format.fprintf fmt "(&&)"
@@ -1787,9 +1745,9 @@ let pp_mllam fmt l =
| Mk_empty_instance -> Format.fprintf fmt "Univ.Instance.empty"
| Coq_primitive (op,None) ->
Format.fprintf fmt "no_check_%s" (CPrimitives.to_string op)
- | Coq_primitive (op, Some (prefix,kn)) ->
+ | Coq_primitive (op, Some (prefix,(c,_))) ->
Format.fprintf fmt "%s %a" (CPrimitives.to_string op)
- pp_mllam (MLglobal (Gconstant (prefix, kn)))
+ pp_mllam (MLglobal (Gconstant (prefix,c)))
in
Format.fprintf fmt "@[%a@]" pp_mllam l
@@ -1903,7 +1861,7 @@ let compile_constant env sigma prefix ~interactive con cb =
let t = Mod_subst.force_constr t in
let code = lambda_of_constr env sigma t in
if !Flags.debug then Feedback.msg_debug (Pp.str "Generated lambda code");
- let is_lazy = is_lazy env prefix t in
+ 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
diff --git a/kernel/nativeconv.ml b/kernel/nativeconv.ml
index f5d7ab3c9d..baa290367f 100644
--- a/kernel/nativeconv.ml
+++ b/kernel/nativeconv.ml
@@ -34,6 +34,8 @@ let rec conv_val env pb lvl v1 v2 cu =
conv_accu env pb lvl k1 k2 cu
| Vconst i1, Vconst i2 ->
if Int.equal i1 i2 then cu else raise NotConvertible
+ | Vint64 i1, Vint64 i2 ->
+ if Int64.equal i1 i2 then cu else raise NotConvertible
| Vblock b1, Vblock b2 ->
let n1 = block_size b1 in
let n2 = block_size b2 in
@@ -47,7 +49,7 @@ let rec conv_val env pb lvl v1 v2 cu =
aux lvl max b1 b2 (i+1) cu
in
aux lvl (n1-1) b1 b2 0 cu
- | Vaccu _, _ | Vconst _, _ | Vblock _, _ -> raise NotConvertible
+ | Vaccu _, _ | Vconst _, _ | Vint64 _, _ | Vblock _, _ -> raise NotConvertible
and conv_accu env pb lvl k1 k2 cu =
let n1 = accu_nargs k1 in
diff --git a/kernel/nativeinstr.mli b/kernel/nativeinstr.mli
deleted file mode 100644
index 2d8e2ba2f0..0000000000
--- a/kernel/nativeinstr.mli
+++ /dev/null
@@ -1,59 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-open Names
-open Constr
-open Nativevalues
-
-(** This file defines the lambda code for the native compiler. It has been
-extracted from Nativelambda.ml because of the retroknowledge architecture. *)
-
-type prefix = string
-
-type uint =
- | UintVal of Uint31.t
- | UintDigits of prefix * constructor * lambda array
- | UintDecomp of prefix * constructor * lambda
-
-and lambda =
- | Lrel of Name.t * int
- | Lvar of Id.t
- | Lmeta of metavariable * lambda (* type *)
- | Levar of Evar.t * lambda array (* arguments *)
- | Lprod of lambda * lambda
- | Llam of Name.t array * lambda
- | Llet of Name.t * lambda * lambda
- | Lapp of lambda * lambda array
- | Lconst of prefix * pconstant
- | Lproj of prefix * inductive * int (* prefix, inductive, index starting from 0 *)
- | Lprim of prefix * Constant.t * CPrimitives.t * lambda array
- | Lcase of annot_sw * lambda * lambda * lam_branches
- (* annotations, term being matched, accu, branches *)
- | Lif of lambda * lambda * lambda
- | Lfix of (int array * (string * inductive) array * int) * fix_decl
- | Lcofix of int * fix_decl (* must be in eta-expanded form *)
- | Lmakeblock of prefix * pconstructor * int * lambda array
- (* prefix, constructor name, constructor tag, arguments *)
- (* A fully applied constructor *)
- | Lconstruct of prefix * pconstructor
- (* A partially applied constructor *)
- | Luint of uint
- | Lval of Nativevalues.t
- | Lsort of Sorts.t
- | Lind of prefix * pinductive
- | Llazy
- | Lforce
-
-(* Cofixpoints have to be in eta-expanded form for their call-by-need evaluation
-to be correct. Otherwise, memoization of previous evaluations will be applied
-again to extra arguments (see #7333). *)
-
-and lam_branches = (constructor * Name.t array * lambda) array
-
-and fix_decl = Name.t array * lambda array * lambda array
diff --git a/kernel/nativelambda.ml b/kernel/nativelambda.ml
index 70cb8691c6..0869f94042 100644
--- a/kernel/nativelambda.ml
+++ b/kernel/nativelambda.ml
@@ -14,12 +14,46 @@ open Constr
open Declarations
open Environ
open Nativevalues
-open Nativeinstr
module RelDecl = Context.Rel.Declaration
-
-exception NotClosed
+(** This file defines the lambda code generation phase of the native compiler *)
+type prefix = string
+
+type lambda =
+ | Lrel of Name.t * int
+ | Lvar of Id.t
+ | Lmeta of metavariable * lambda (* type *)
+ | Levar of Evar.t * lambda array (* arguments *)
+ | Lprod of lambda * lambda
+ | Llam of Name.t array * lambda
+ | Lrec of Name.t * lambda
+ | Llet of Name.t * lambda * lambda
+ | Lapp of lambda * lambda array
+ | Lconst of prefix * pconstant
+ | Lproj of prefix * inductive * int (* prefix, inductive, index starting from 0 *)
+ | Lprim of prefix * pconstant * CPrimitives.t * lambda array
+ (* No check if None *)
+ | Lcase of annot_sw * lambda * lambda * lam_branches
+ (* annotations, term being matched, accu, branches *)
+ | Lif of lambda * lambda * lambda
+ | Lfix of (int array * (string * inductive) array * int) * fix_decl
+ | Lcofix of int * fix_decl
+ | Lmakeblock of prefix * pconstructor * int * lambda array
+ (* prefix, constructor Name.t, constructor tag, arguments *)
+ (* A fully applied constructor *)
+ | Lconstruct of prefix * pconstructor (* prefix, constructor Name.t *)
+ (* A partially applied constructor *)
+ | Luint of Uint63.t
+ | Lval of Nativevalues.t
+ | Lsort of Sorts.t
+ | Lind of prefix * pinductive
+ | Llazy
+ | Lforce
+
+and lam_branches = (constructor * Name.t array * lambda) array
+
+and fix_decl = Name.t array * lambda array * lambda array
type evars =
{ evars_val : existential -> constr option;
@@ -84,9 +118,9 @@ let get_const_prefix env c =
(* A generic map function *)
-let rec map_lam_with_binders g f n lam =
+let map_lam_with_binders g f n lam =
match lam with
- | Lrel _ | Lvar _ | Lconst _ | Lproj _ | Lval _ | Lsort _ | Lind _
+ | Lrel _ | Lvar _ | Lconst _ | Lproj _ | Lval _ | Lsort _ | Lind _ | Luint _
| Lconstruct _ | Llazy | Lforce | Lmeta _ -> lam
| Lprod(dom,codom) ->
let dom' = f n dom in
@@ -95,6 +129,9 @@ let rec map_lam_with_binders g f n lam =
| Llam(ids,body) ->
let body' = f (g (Array.length ids) n) body in
if body == body' then lam else mkLlam ids body'
+ | Lrec(id,body) ->
+ let body' = f (g 1 n) body in
+ if body == body' then lam else Lrec(id,body')
| Llet(id,def,body) ->
let def' = f n def in
let body' = f (g 1 n) body in
@@ -135,23 +172,10 @@ let rec map_lam_with_binders g f n lam =
| Lmakeblock(prefix,cn,tag,args) ->
let args' = Array.Smart.map (f n) args in
if args == args' then lam else Lmakeblock(prefix,cn,tag,args')
- | Luint u ->
- let u' = map_uint g f n u in
- if u == u' then lam else Luint u'
| Levar (evk, args) ->
let args' = Array.Smart.map (f n) args in
if args == args' then lam else Levar (evk, args')
-and map_uint _g f n u =
- match u with
- | UintVal _ -> u
- | UintDigits(prefix,c,args) ->
- let args' = Array.Smart.map (f n) args in
- if args == args' then u else UintDigits(prefix,c,args')
- | UintDecomp(prefix,c,a) ->
- let a' = f n a in
- if a == a' then u else UintDecomp(prefix,c,a')
-
(*s Lift and substitution *)
let rec lam_exlift el lam =
@@ -186,7 +210,7 @@ let lam_subst_args subst args =
(* [simplify subst lam] simplify the expression [lam_subst subst lam] *)
(* that is : *)
(* - Reduce [let] is the definition can be substituted i.e: *)
-(* - a variable (rel or identifier) *)
+(* - a variable (rel or Id.t) *)
(* - a constant *)
(* - a structured constant *)
(* - a function *)
@@ -298,7 +322,7 @@ let is_value lc =
match lc with
| Lval _ -> true
| Lmakeblock(_,_,_,args) when Array.is_empty args -> true
- | Luint (UintVal _) -> true
+ | Luint _ -> true
| _ -> false
let get_value lc =
@@ -306,7 +330,7 @@ let get_value lc =
| Lval v -> v
| Lmakeblock(_,_,tag,args) when Array.is_empty args ->
Nativevalues.mk_int tag
- | Luint (UintVal i) -> Nativevalues.mk_uint i
+ | Luint i -> Nativevalues.mk_uint i
| _ -> raise Not_found
let make_args start _end =
@@ -333,6 +357,20 @@ let rec get_alias env (kn, u as p) =
| Cemitcodes.BCalias kn' -> get_alias env (kn', u)
| _ -> p
+let prim env kn p args =
+ let prefix = get_const_prefix env (fst kn) in
+ Lprim(prefix, kn, p, args)
+
+let expand_prim env kn op arity =
+ let ids = Array.make arity Anonymous in
+ let args = make_args arity 1 in
+ Llam(ids, prim env kn op args)
+
+let lambda_of_prim env kn op args =
+ let arity = CPrimitives.arity op in
+ if Array.length args >= arity then prim env kn op args
+ else mkLapp (expand_prim env kn op arity) args
+
(*i Global environment *)
let get_names decl =
@@ -368,22 +406,9 @@ module Cache =
r
end
-let is_lazy env prefix t =
- match kind t with
- | App (f,_args) ->
- begin match kind f with
- | Construct (c,_) ->
- let gr = GlobRef.IndRef (fst c) in
- (try
- let _ =
- Retroknowledge.get_native_before_match_info env.retroknowledge
- gr prefix c Llazy;
- in
- false
- with Not_found -> true)
- | _ -> true
- end
- | LetIn _ | Case _ | Proj _ -> true
+let is_lazy t =
+ match Constr.kind t with
+ | App _ | LetIn _ | Case _ | Proj _ -> true
| _ -> false
let evar_value sigma ev = sigma.evars_val ev
@@ -482,13 +507,6 @@ let rec lambda_of_constr cache env sigma c =
in
(* translation of the argument *)
let la = lambda_of_constr cache env sigma a in
- let gr = GlobRef.IndRef ind in
- let la =
- try
- Retroknowledge.get_native_before_match_info (env).retroknowledge
- gr prefix (ind,1) la
- with Not_found -> la
- in
(* translation of the type *)
let lt = lambda_of_constr cache env sigma t in
(* translation of branches *)
@@ -519,7 +537,7 @@ let rec lambda_of_constr cache env sigma c =
let env = Environ.push_rec_types (names, type_bodies, rec_bodies) env in
let lbodies = lambda_of_args cache env sigma 0 rec_bodies in
Lfix((pos, inds, i), (names, ltypes, lbodies))
-
+
| CoFix(init,(names,type_bodies,rec_bodies)) ->
let rec_bodies = Array.map2 (Reduction.eta_expand env) rec_bodies type_bodies in
let ltypes = lambda_of_args cache env sigma 0 type_bodies in
@@ -527,27 +545,22 @@ let rec lambda_of_constr cache env sigma c =
let lbodies = lambda_of_args cache env sigma 0 rec_bodies in
Lcofix(init, (names, ltypes, lbodies))
+ | Int i -> Luint i
+
and lambda_of_app cache env sigma f args =
match kind f with
| Const (_kn,_u as c) ->
let kn,u = get_alias env c in
let cb = lookup_constant kn env in
- (try
- let prefix = get_const_prefix env kn in
- (* We delay the compilation of arguments to avoid an exponential behavior *)
- let f = Retroknowledge.get_native_compiling_info
- (env).retroknowledge (GlobRef.ConstRef kn) prefix in
- let args = lambda_of_args cache env sigma 0 args in
- f args
- with Not_found ->
begin match cb.const_body with
+ | Primitive op -> lambda_of_prim env c op (lambda_of_args cache env sigma 0 args)
| Def csubst -> (* TODO optimize if f is a proj and argument is known *)
if cb.const_inline_code then
lambda_of_app cache env sigma (Mod_subst.force_constr csubst) args
else
let prefix = get_const_prefix env kn in
let t =
- if is_lazy env prefix (Mod_subst.force_constr csubst) then
+ if is_lazy (Mod_subst.force_constr csubst) then
mkLapp Lforce [|Lconst (prefix, (kn,u))|]
else Lconst (prefix, (kn,u))
in
@@ -555,34 +568,18 @@ and lambda_of_app cache env sigma f args =
| OpaqueDef _ | Undef _ ->
let prefix = get_const_prefix env kn in
mkLapp (Lconst (prefix, (kn,u))) (lambda_of_args cache env sigma 0 args)
- end)
+ end
| Construct (c,u) ->
let tag, nparams, arity = Cache.get_construct_info cache env c in
let expected = nparams + arity in
let nargs = Array.length args in
let prefix = get_mind_prefix env (fst (fst c)) in
- let gr = GlobRef.ConstructRef c in
if Int.equal nargs expected then
- try
- try
- Retroknowledge.get_native_constant_static_info
- (env).retroknowledge
- gr args
- with NotClosed ->
- assert (Int.equal nparams 0); (* should be fine for int31 *)
- let args = lambda_of_args cache env sigma nparams args in
- Retroknowledge.get_native_constant_dynamic_info
- (env).retroknowledge gr prefix c args
- with Not_found ->
let args = lambda_of_args cache env sigma nparams args in
makeblock env c u tag args
else
let args = lambda_of_args cache env sigma 0 args in
- (try
- Retroknowledge.get_native_constant_dynamic_info
- (env).retroknowledge gr prefix c args
- with Not_found ->
- mkLapp (Lconstruct (prefix, (c,u))) args)
+ mkLapp (Lconstruct (prefix, (c,u))) args
| _ ->
let f = lambda_of_constr cache env sigma f in
let args = lambda_of_args cache env sigma 0 args in
@@ -615,45 +612,3 @@ let lambda_of_constr env sigma c =
let mk_lazy c =
mkLapp Llazy [|c|]
-
-(** Retroknowledge, to be removed once we move to primitive machine integers *)
-let compile_static_int31 fc args =
- if not fc then raise Not_found else
- Luint (UintVal
- (Uint31.of_int (Array.fold_left
- (fun temp_i -> fun t -> match kind t with
- | Construct ((_,d),_) -> 2*temp_i+d-1
- | _ -> raise NotClosed)
- 0 args)))
-
-let compile_dynamic_int31 fc prefix c args =
- if not fc then raise Not_found else
- Luint (UintDigits (prefix,c,args))
-
-(* We are relying here on the order of digits constructors *)
-let digits_from_uint digits_ind prefix i =
- let d0 = Lconstruct (prefix, ((digits_ind, 1), Univ.Instance.empty)) in
- let d1 = Lconstruct (prefix, ((digits_ind, 2), Univ.Instance.empty)) in
- let digits = Array.make 31 d0 in
- for k = 0 to 30 do
- if Int.equal ((Uint31.to_int i lsr k) land 1) 1 then
- digits.(30-k) <- d1
- done;
- digits
-
-let before_match_int31 digits_ind fc prefix c t =
- if not fc then
- raise Not_found
- else
- match t with
- | Luint (UintVal i) ->
- let digits = digits_from_uint digits_ind prefix i in
- mkLapp (Lconstruct (prefix,(c, Univ.Instance.empty))) digits
- | Luint (UintDigits (prefix,c,args)) ->
- mkLapp (Lconstruct (prefix,(c, Univ.Instance.empty))) args
- | _ -> Luint (UintDecomp (prefix,c,t))
-
-let compile_prim prim kn fc prefix args =
- if not fc then raise Not_found
- else
- Lprim(prefix, kn, prim, args)
diff --git a/kernel/nativelambda.mli b/kernel/nativelambda.mli
index 7b20258929..eb06522a33 100644
--- a/kernel/nativelambda.mli
+++ b/kernel/nativelambda.mli
@@ -10,9 +10,45 @@
open Names
open Constr
open Environ
-open Nativeinstr
+open Nativevalues
(** This file defines the lambda code generation phase of the native compiler *)
+type prefix = string
+
+type lambda =
+ | Lrel of Name.t * int
+ | Lvar of Id.t
+ | Lmeta of metavariable * lambda (* type *)
+ | Levar of Evar.t * lambda array (* arguments *)
+ | Lprod of lambda * lambda
+ | Llam of Name.t array * lambda
+ | Lrec of Name.t * lambda
+ | Llet of Name.t * lambda * lambda
+ | Lapp of lambda * lambda array
+ | Lconst of prefix * pconstant
+ | Lproj of prefix * inductive * int (* prefix, inductive, index starting from 0 *)
+ | Lprim of prefix * pconstant * CPrimitives.t * lambda array
+ | Lcase of annot_sw * lambda * lambda * lam_branches
+ (* annotations, term being matched, accu, branches *)
+ | Lif of lambda * lambda * lambda
+ | Lfix of (int array * (string * inductive) array * int) * fix_decl
+ | Lcofix of int * fix_decl
+ | Lmakeblock of prefix * pconstructor * int * lambda array
+ (* prefix, constructor Name.t, constructor tag, arguments *)
+ (* A fully applied constructor *)
+ | Lconstruct of prefix * pconstructor (* prefix, constructor Name.t *)
+ (* A partially applied constructor *)
+ | Luint of Uint63.t
+ | Lval of Nativevalues.t
+ | Lsort of Sorts.t
+ | Lind of prefix * pinductive
+ | Llazy
+ | Lforce
+
+and lam_branches = (constructor * Name.t array * lambda) array
+
+and fix_decl = Name.t array * lambda array * lambda array
+
type evars =
{ evars_val : existential -> constr option;
evars_metas : metavariable -> types }
@@ -22,7 +58,7 @@ val empty_evars : evars
val decompose_Llam : lambda -> Name.t array * lambda
val decompose_Llam_Llet : lambda -> (Name.t * lambda option) array * lambda
-val is_lazy : env -> prefix -> constr -> bool
+val is_lazy : constr -> bool
val mk_lazy : lambda -> lambda
val get_mind_prefix : env -> MutInd.t -> string
@@ -30,14 +66,3 @@ val get_mind_prefix : env -> MutInd.t -> string
val get_alias : env -> pconstant -> pconstant
val lambda_of_constr : env -> evars -> Constr.constr -> lambda
-
-val compile_static_int31 : bool -> Constr.constr array -> lambda
-
-val compile_dynamic_int31 : bool -> prefix -> constructor -> lambda array ->
- lambda
-
-val before_match_int31 : inductive -> bool -> prefix -> constructor -> lambda ->
- lambda
-
-val compile_prim : CPrimitives.t -> Constant.t -> bool -> prefix -> lambda array ->
- lambda
diff --git a/kernel/nativevalues.ml b/kernel/nativevalues.ml
index 93e74af845..a6b48cd7e3 100644
--- a/kernel/nativevalues.ml
+++ b/kernel/nativevalues.ml
@@ -196,11 +196,17 @@ let dummy_value : unit -> t =
fun () _ -> anomaly ~label:"native" (Pp.str "Evaluation failed.")
let cast_accu v = (Obj.magic v:accumulator)
+[@@ocaml.inline always]
let mk_int (x : int) = (Obj.magic x : t)
+[@@ocaml.inline always]
+
(* Coq's booleans are reversed... *)
let mk_bool (b : bool) = (Obj.magic (not b) : t)
-let mk_uint (x : Uint31.t) = (Obj.magic x : t)
+[@@ocaml.inline always]
+
+let mk_uint (x : Uint63.t) = (Obj.magic x : t)
+[@@ocaml.inline always]
type block
@@ -216,8 +222,9 @@ type kind_of_value =
| Vaccu of accumulator
| Vfun of (t -> t)
| Vconst of int
+ | Vint64 of int64
| Vblock of block
-
+
let kind_of_value (v:t) =
let o = Obj.repr v in
if Obj.is_int o then Vconst (Obj.magic v)
@@ -225,8 +232,8 @@ let kind_of_value (v:t) =
let tag = Obj.tag o in
if Int.equal tag accumulate_tag then
Vaccu (Obj.magic v)
- else
- if (tag < Obj.lazy_tag) then Vblock (Obj.magic v)
+ else if Int.equal tag Obj.custom_tag then Vint64 (Obj.magic v)
+ else if (tag < Obj.lazy_tag) then Vblock (Obj.magic v)
else
(* assert (tag = Obj.closure_tag || tag = Obj.infix_tag);
or ??? what is 1002*)
@@ -236,92 +243,105 @@ let kind_of_value (v:t) =
let is_int (x:t) =
let o = Obj.repr x in
- Obj.is_int o
+ Obj.is_int o || Int.equal (Obj.tag o) Obj.custom_tag
let val_to_int (x:t) = (Obj.magic x : int)
+[@@ocaml.inline always]
-let to_uint (x:t) = (Obj.magic x : Uint31.t)
-let of_uint (x: Uint31.t) = (Obj.magic x : t)
+let to_uint (x:t) = (Obj.magic x : Uint63.t)
+[@@ocaml.inline always]
let no_check_head0 x =
- of_uint (Uint31.head0 (to_uint x))
+ mk_uint (Uint63.head0 (to_uint x))
+[@@ocaml.inline always]
let head0 accu x =
if is_int x then no_check_head0 x
else accu x
let no_check_tail0 x =
- of_uint (Uint31.tail0 (to_uint x))
+ mk_uint (Uint63.tail0 (to_uint x))
+[@@ocaml.inline always]
let tail0 accu x =
if is_int x then no_check_tail0 x
else accu x
let no_check_add x y =
- of_uint (Uint31.add (to_uint x) (to_uint y))
+ mk_uint (Uint63.add (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let add accu x y =
if is_int x && is_int y then no_check_add x y
else accu x y
let no_check_sub x y =
- of_uint (Uint31.sub (to_uint x) (to_uint y))
+ mk_uint (Uint63.sub (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let sub accu x y =
if is_int x && is_int y then no_check_sub x y
else accu x y
let no_check_mul x y =
- of_uint (Uint31.mul (to_uint x) (to_uint y))
+ mk_uint (Uint63.mul (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let mul accu x y =
if is_int x && is_int y then no_check_mul x y
else accu x y
let no_check_div x y =
- of_uint (Uint31.div (to_uint x) (to_uint y))
+ mk_uint (Uint63.div (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let div accu x y =
if is_int x && is_int y then no_check_div x y
else accu x y
let no_check_rem x y =
- of_uint (Uint31.rem (to_uint x) (to_uint y))
+ mk_uint (Uint63.rem (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let rem accu x y =
if is_int x && is_int y then no_check_rem x y
else accu x y
let no_check_l_sr x y =
- of_uint (Uint31.l_sr (to_uint x) (to_uint y))
+ mk_uint (Uint63.l_sr (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let l_sr accu x y =
if is_int x && is_int y then no_check_l_sr x y
else accu x y
let no_check_l_sl x y =
- of_uint (Uint31.l_sl (to_uint x) (to_uint y))
+ mk_uint (Uint63.l_sl (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let l_sl accu x y =
if is_int x && is_int y then no_check_l_sl x y
else accu x y
let no_check_l_and x y =
- of_uint (Uint31.l_and (to_uint x) (to_uint y))
+ mk_uint (Uint63.l_and (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let l_and accu x y =
if is_int x && is_int y then no_check_l_and x y
else accu x y
let no_check_l_xor x y =
- of_uint (Uint31.l_xor (to_uint x) (to_uint y))
+ mk_uint (Uint63.l_xor (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let l_xor accu x y =
if is_int x && is_int y then no_check_l_xor x y
else accu x y
let no_check_l_or x y =
- of_uint (Uint31.l_or (to_uint x) (to_uint y))
+ mk_uint (Uint63.l_or (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let l_or accu x y =
if is_int x && is_int y then no_check_l_or x y
@@ -337,61 +357,57 @@ type coq_pair =
| Paccu of t
| PPair of t * t
-type coq_zn2z =
- | Zaccu of t
- | ZW0
- | ZWW of t * t
-
let mkCarry b i =
- if b then (Obj.magic (C1(of_uint i)):t)
- else (Obj.magic (C0(of_uint i)):t)
+ if b then (Obj.magic (C1(mk_uint i)):t)
+ else (Obj.magic (C0(mk_uint i)):t)
let no_check_addc x y =
- let s = Uint31.add (to_uint x) (to_uint y) in
- mkCarry (Uint31.lt s (to_uint x)) s
+ let s = Uint63.add (to_uint x) (to_uint y) in
+ mkCarry (Uint63.lt s (to_uint x)) s
+[@@ocaml.inline always]
let addc accu x y =
if is_int x && is_int y then no_check_addc x y
else accu x y
let no_check_subc x y =
- let s = Uint31.sub (to_uint x) (to_uint y) in
- mkCarry (Uint31.lt (to_uint x) (to_uint y)) s
+ let s = Uint63.sub (to_uint x) (to_uint y) in
+ mkCarry (Uint63.lt (to_uint x) (to_uint y)) s
+[@@ocaml.inline always]
let subc accu x y =
if is_int x && is_int y then no_check_subc x y
else accu x y
-let no_check_addcarryc x y =
+let no_check_addCarryC x y =
let s =
- Uint31.add (Uint31.add (to_uint x) (to_uint y))
- (Uint31.of_int 1) in
- mkCarry (Uint31.le s (to_uint x)) s
+ Uint63.add (Uint63.add (to_uint x) (to_uint y))
+ (Uint63.of_int 1) in
+ mkCarry (Uint63.le s (to_uint x)) s
+[@@ocaml.inline always]
-let addcarryc accu x y =
- if is_int x && is_int y then no_check_addcarryc x y
+let addCarryC accu x y =
+ if is_int x && is_int y then no_check_addCarryC x y
else accu x y
-let no_check_subcarryc x y =
+let no_check_subCarryC x y =
let s =
- Uint31.sub (Uint31.sub (to_uint x) (to_uint y))
- (Uint31.of_int 1) in
- mkCarry (Uint31.le (to_uint x) (to_uint y)) s
+ Uint63.sub (Uint63.sub (to_uint x) (to_uint y))
+ (Uint63.of_int 1) in
+ mkCarry (Uint63.le (to_uint x) (to_uint y)) s
+[@@ocaml.inline always]
-let subcarryc accu x y =
- if is_int x && is_int y then no_check_subcarryc x y
+let subCarryC accu x y =
+ if is_int x && is_int y then no_check_subCarryC x y
else accu x y
let of_pair (x, y) =
- (Obj.magic (PPair(of_uint x, of_uint y)):t)
-
-let zn2z_of_pair (x,y) =
- if Uint31.equal x (Uint31.of_uint 0) &&
- Uint31.equal y (Uint31.of_uint 0) then Obj.magic ZW0
- else (Obj.magic (ZWW(of_uint x, of_uint y)) : t)
+ (Obj.magic (PPair(mk_uint x, mk_uint y)):t)
+[@@ocaml.inline always]
let no_check_mulc x y =
- zn2z_of_pair(Uint31.mulc (to_uint x) (to_uint y))
+ of_pair (Uint63.mulc (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let mulc accu x y =
if is_int x && is_int y then no_check_mulc x y
@@ -399,7 +415,8 @@ let mulc accu x y =
let no_check_diveucl x y =
let i1, i2 = to_uint x, to_uint y in
- of_pair(Uint31.div i1 i2, Uint31.rem i1 i2)
+ of_pair(Uint63.div i1 i2, Uint63.rem i1 i2)
+[@@ocaml.inline always]
let diveucl accu x y =
if is_int x && is_int y then no_check_diveucl x y
@@ -407,21 +424,20 @@ let diveucl accu x y =
let no_check_div21 x y z =
let i1, i2, i3 = to_uint x, to_uint y, to_uint z in
- of_pair (Uint31.div21 i1 i2 i3)
+ of_pair (Uint63.div21 i1 i2 i3)
+[@@ocaml.inline always]
let div21 accu x y z =
if is_int x && is_int y && is_int z then no_check_div21 x y z
else accu x y z
-let no_check_addmuldiv x y z =
+let no_check_addMulDiv x y z =
let p, i, j = to_uint x, to_uint y, to_uint z in
- let p' = Uint31.to_int p in
- of_uint (Uint31.l_or
- (Uint31.l_sl i p)
- (Uint31.l_sr j (Uint31.of_int (31 - p'))))
+ mk_uint (Uint63.addmuldiv p i j)
+[@@ocaml.inline always]
-let addmuldiv accu x y z =
- if is_int x && is_int y && is_int z then no_check_addmuldiv x y z
+let addMulDiv accu x y z =
+ if is_int x && is_int y && is_int z then no_check_addMulDiv x y z
else accu x y z
[@@@ocaml.warning "-34"]
@@ -436,29 +452,32 @@ type coq_cmp =
| CmpLt
| CmpGt
-let no_check_eq x y =
- mk_bool (Uint31.equal (to_uint x) (to_uint y))
+let no_check_eq x y =
+ mk_bool (Uint63.equal (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let eq accu x y =
if is_int x && is_int y then no_check_eq x y
else accu x y
let no_check_lt x y =
- mk_bool (Uint31.lt (to_uint x) (to_uint y))
+ mk_bool (Uint63.lt (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let lt accu x y =
if is_int x && is_int y then no_check_lt x y
else accu x y
let no_check_le x y =
- mk_bool (Uint31.le (to_uint x) (to_uint y))
+ mk_bool (Uint63.le (to_uint x) (to_uint y))
+[@@ocaml.inline always]
let le accu x y =
if is_int x && is_int y then no_check_le x y
else accu x y
let no_check_compare x y =
- match Uint31.compare (to_uint x) (to_uint y) with
+ match Uint63.compare (to_uint x) (to_uint y) with
| x when x < 0 -> (Obj.magic CmpLt:t)
| 0 -> (Obj.magic CmpEq:t)
| _ -> (Obj.magic CmpGt:t)
@@ -467,6 +486,11 @@ let compare accu x y =
if is_int x && is_int y then no_check_compare x y
else accu x y
+let print x =
+ Printf.fprintf stderr "%s" (Uint63.to_string (to_uint x));
+ flush stderr;
+ x
+
let hobcnv = Array.init 256 (fun i -> Printf.sprintf "%02x" i)
let bohcnv = Array.init 256 (fun i -> i -
(if 0x30 <= i then 0x30 else 0) -
@@ -491,63 +515,3 @@ let str_decode s =
Buffer.add_char mshl_expr (bin_of_hex (Bytes.to_string buf))
done;
Marshal.from_bytes (Buffer.to_bytes mshl_expr) 0
-
-(** Retroknowledge, to be removed when we switch to primitive integers *)
-
-(* This will be unsafe with 63-bits integers *)
-let digit_to_uint d = (Obj.magic d : Uint31.t)
-
-let mk_I31_accu c x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17
- x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 =
- if is_int x0 && is_int x1 && is_int x2 && is_int x3 && is_int x4 && is_int x5
- && is_int x6 && is_int x7 && is_int x8 && is_int x9 && is_int x10
- && is_int x11 && is_int x12 && is_int x13 && is_int x14 && is_int x15
- && is_int x16 && is_int x17 && is_int x18 && is_int x19 && is_int x20
- && is_int x21 && is_int x22 && is_int x23 && is_int x24 && is_int x25
- && is_int x26 && is_int x27 && is_int x28 && is_int x29 && is_int x30
- then
- let r = digit_to_uint x0 in
- let r = Uint31.add_digit r (digit_to_uint x1) in
- let r = Uint31.add_digit r (digit_to_uint x2) in
- let r = Uint31.add_digit r (digit_to_uint x3) in
- let r = Uint31.add_digit r (digit_to_uint x4) in
- let r = Uint31.add_digit r (digit_to_uint x5) in
- let r = Uint31.add_digit r (digit_to_uint x6) in
- let r = Uint31.add_digit r (digit_to_uint x7) in
- let r = Uint31.add_digit r (digit_to_uint x8) in
- let r = Uint31.add_digit r (digit_to_uint x9) in
- let r = Uint31.add_digit r (digit_to_uint x10) in
- let r = Uint31.add_digit r (digit_to_uint x11) in
- let r = Uint31.add_digit r (digit_to_uint x12) in
- let r = Uint31.add_digit r (digit_to_uint x13) in
- let r = Uint31.add_digit r (digit_to_uint x14) in
- let r = Uint31.add_digit r (digit_to_uint x15) in
- let r = Uint31.add_digit r (digit_to_uint x16) in
- let r = Uint31.add_digit r (digit_to_uint x17) in
- let r = Uint31.add_digit r (digit_to_uint x18) in
- let r = Uint31.add_digit r (digit_to_uint x19) in
- let r = Uint31.add_digit r (digit_to_uint x20) in
- let r = Uint31.add_digit r (digit_to_uint x21) in
- let r = Uint31.add_digit r (digit_to_uint x22) in
- let r = Uint31.add_digit r (digit_to_uint x23) in
- let r = Uint31.add_digit r (digit_to_uint x24) in
- let r = Uint31.add_digit r (digit_to_uint x25) in
- let r = Uint31.add_digit r (digit_to_uint x26) in
- let r = Uint31.add_digit r (digit_to_uint x27) in
- let r = Uint31.add_digit r (digit_to_uint x28) in
- let r = Uint31.add_digit r (digit_to_uint x29) in
- let r = Uint31.add_digit r (digit_to_uint x30) in
- mk_uint r
- else
- c x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20
- x21 x22 x23 x24 x25 x26 x27 x28 x29 x30
-
-let decomp_uint c v =
- if is_int v then
- let r = ref c in
- let v = val_to_int v in
- for i = 30 downto 0 do
- r := (!r) (mk_int ((v lsr i) land 1));
- done;
- !r
- else v
diff --git a/kernel/nativevalues.mli b/kernel/nativevalues.mli
index 10689941e8..58cb6e2c30 100644
--- a/kernel/nativevalues.mli
+++ b/kernel/nativevalues.mli
@@ -78,8 +78,13 @@ val mk_const : tag -> t
val mk_block : tag -> t array -> t
val mk_bool : bool -> t
+[@@ocaml.inline always]
+
val mk_int : int -> t
-val mk_uint : Uint31.t -> t
+[@@ocaml.inline always]
+
+val mk_uint : Uint63.t -> t
+[@@ocaml.inline always]
val napply : t -> t array -> t
(* Functions over accumulators *)
@@ -90,6 +95,8 @@ val args_of_accu : accumulator -> t array
val accu_nargs : accumulator -> int
val cast_accu : t -> accumulator
+[@@ocaml.inline always]
+
(* Functions over block: i.e constructors *)
type block
@@ -106,6 +113,7 @@ type kind_of_value =
| Vaccu of accumulator
| Vfun of (t -> t)
| Vconst of int
+ | Vint64 of int64
| Vblock of block
val kind_of_value : t -> kind_of_value
@@ -136,51 +144,90 @@ val l_or : t -> t -> t -> t
val addc : t -> t -> t -> t
val subc : t -> t -> t -> t
-val addcarryc : t -> t -> t -> t
-val subcarryc : t -> t -> t -> t
+val addCarryC : t -> t -> t -> t
+val subCarryC : t -> t -> t -> t
val mulc : t -> t -> t -> t
val diveucl : t -> t -> t -> t
val div21 : t -> t -> t -> t -> t
-val addmuldiv : t -> t -> t -> t -> t
+val addMulDiv : t -> t -> t -> t -> t
val eq : t -> t -> t -> t
val lt : t -> t -> t -> t
val le : t -> t -> t -> t
val compare : t -> t -> t -> t
+val print : t -> t
+
(* Function without check *)
val no_check_head0 : t -> t
+[@@ocaml.inline always]
+
val no_check_tail0 : t -> t
+[@@ocaml.inline always]
val no_check_add : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_sub : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_mul : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_div : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_rem : t -> t -> t
+[@@ocaml.inline always]
val no_check_l_sr : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_l_sl : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_l_and : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_l_xor : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_l_or : t -> t -> t
+[@@ocaml.inline always]
val no_check_addc : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_subc : t -> t -> t
-val no_check_addcarryc : t -> t -> t
-val no_check_subcarryc : t -> t -> t
+[@@ocaml.inline always]
+
+val no_check_addCarryC : t -> t -> t
+[@@ocaml.inline always]
+
+val no_check_subCarryC : t -> t -> t
+[@@ocaml.inline always]
val no_check_mulc : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_diveucl : t -> t -> t
+[@@ocaml.inline always]
val no_check_div21 : t -> t -> t -> t
-val no_check_addmuldiv : t -> t -> t -> t
+[@@ocaml.inline always]
+
+val no_check_addMulDiv : t -> t -> t -> t
+[@@ocaml.inline always]
val no_check_eq : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_lt : t -> t -> t
+[@@ocaml.inline always]
+
val no_check_le : t -> t -> t
-val no_check_compare : t -> t -> t
+[@@ocaml.inline always]
-val mk_I31_accu : t
-val decomp_uint : t -> t -> t
+val no_check_compare : t -> t -> t
diff --git a/kernel/primred.ml b/kernel/primred.ml
new file mode 100644
index 0000000000..d95d7de7aa
--- /dev/null
+++ b/kernel/primred.ml
@@ -0,0 +1,208 @@
+(* Reduction of native operators *)
+open Names
+open CPrimitives
+open Retroknowledge
+open Environ
+open CErrors
+
+let add_retroknowledge env action =
+ match action with
+ | Register_type(PT_int63,c) ->
+ let retro = env.retroknowledge in
+ let retro =
+ match retro.retro_int63 with
+ | None -> { retro with retro_int63 = Some c }
+ | Some c' -> assert (Constant.equal c c'); retro in
+ set_retroknowledge env retro
+ | Register_ind(pit,ind) ->
+ let retro = env.retroknowledge in
+ let retro =
+ match pit with
+ | PIT_bool ->
+ let r =
+ match retro.retro_bool with
+ | None -> ((ind,1), (ind,2))
+ | Some (((ind',_),_) as t) -> assert (eq_ind ind ind'); t in
+ { retro with retro_bool = Some r }
+ | PIT_carry ->
+ let r =
+ match retro.retro_carry with
+ | None -> ((ind,1), (ind,2))
+ | Some (((ind',_),_) as t) -> assert (eq_ind ind ind'); t in
+ { retro with retro_carry = Some r }
+ | PIT_pair ->
+ let r =
+ match retro.retro_pair with
+ | None -> (ind,1)
+ | Some ((ind',_) as t) -> assert (eq_ind ind ind'); t in
+ { retro with retro_pair = Some r }
+ | PIT_cmp ->
+ let r =
+ match retro.retro_cmp with
+ | None -> ((ind,1), (ind,2), (ind,3))
+ | Some (((ind',_),_,_) as t) -> assert (eq_ind ind ind'); t in
+ { retro with retro_cmp = Some r }
+ in
+ set_retroknowledge env retro
+ | Register_inline(c) ->
+ let (cb,r) = lookup_constant_key c env in
+ let cb = {cb with Declarations.const_inline_code = true} in
+ add_constant_key c cb !(fst r) env
+
+let get_int_type env =
+ match env.retroknowledge.retro_int63 with
+ | Some c -> c
+ | None -> anomaly Pp.(str"Reduction of primitive: int63 not registered")
+
+let get_bool_constructors env =
+ match env.retroknowledge.retro_bool with
+ | Some r -> r
+ | None -> anomaly Pp.(str"Reduction of primitive: bool not registered")
+
+let get_carry_constructors env =
+ match env.retroknowledge.retro_carry with
+ | Some r -> r
+ | None -> anomaly Pp.(str"Reduction of primitive: carry not registered")
+
+let get_pair_constructor env =
+ match env.retroknowledge.retro_pair with
+ | Some c -> c
+ | None -> anomaly Pp.(str"Reduction of primitive: pair not registered")
+
+let get_cmp_constructors env =
+ match env.retroknowledge.retro_cmp with
+ | Some r -> r
+ | None -> anomaly Pp.(str"Reduction of primitive: cmp not registered")
+
+exception NativeDestKO
+
+module type RedNativeEntries =
+ sig
+ type elem
+ type args
+ type evd (* will be unit in kernel, evar_map outside *)
+
+ val get : args -> int -> elem
+ val get_int : evd -> elem -> Uint63.t
+ val mkInt : env -> Uint63.t -> elem
+ val mkBool : env -> bool -> elem
+ val mkCarry : env -> bool -> elem -> elem (* true if carry *)
+ val mkIntPair : env -> elem -> elem -> elem
+ val mkLt : env -> elem
+ val mkEq : env -> elem
+ val mkGt : env -> elem
+
+ end
+
+module type RedNative =
+ sig
+ type elem
+ type args
+ type evd
+ val red_prim : env -> evd -> CPrimitives.t -> args -> elem option
+ end
+
+module RedNative (E:RedNativeEntries) :
+ RedNative with type elem = E.elem
+ with type args = E.args
+ with type evd = E.evd =
+struct
+ type elem = E.elem
+ type args = E.args
+ type evd = E.evd
+
+ let get_int evd args i = E.get_int evd (E.get args i)
+
+ let get_int1 evd args = get_int evd args 0
+
+ let get_int2 evd args = get_int evd args 0, get_int evd args 1
+
+ let get_int3 evd args =
+ get_int evd args 0, get_int evd args 1, get_int evd args 2
+
+ let red_prim_aux env evd op args =
+ let open CPrimitives in
+ match op with
+ | Int63head0 ->
+ let i = get_int1 evd args in E.mkInt env (Uint63.head0 i)
+ | Int63tail0 ->
+ let i = get_int1 evd args in E.mkInt env (Uint63.tail0 i)
+ | Int63add ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.add i1 i2)
+ | Int63sub ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.sub i1 i2)
+ | Int63mul ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.mul i1 i2)
+ | Int63div ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.div i1 i2)
+ | Int63mod ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.rem i1 i2)
+ | Int63lsr ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.l_sr i1 i2)
+ | Int63lsl ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.l_sl i1 i2)
+ | Int63land ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.l_and i1 i2)
+ | Int63lor ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.l_or i1 i2)
+ | Int63lxor ->
+ let i1, i2 = get_int2 evd args in E.mkInt env (Uint63.l_xor i1 i2)
+ | Int63addc ->
+ let i1, i2 = get_int2 evd args in
+ let s = Uint63.add i1 i2 in
+ E.mkCarry env (Uint63.lt s i1) (E.mkInt env s)
+ | Int63subc ->
+ let i1, i2 = get_int2 evd args in
+ let s = Uint63.sub i1 i2 in
+ E.mkCarry env (Uint63.lt i1 i2) (E.mkInt env s)
+ | Int63addCarryC ->
+ let i1, i2 = get_int2 evd args in
+ let s = Uint63.add (Uint63.add i1 i2) (Uint63.of_int 1) in
+ E.mkCarry env (Uint63.le s i1) (E.mkInt env s)
+ | Int63subCarryC ->
+ let i1, i2 = get_int2 evd args in
+ let s = Uint63.sub (Uint63.sub i1 i2) (Uint63.of_int 1) in
+ E.mkCarry env (Uint63.le i1 i2) (E.mkInt env s)
+ | Int63mulc ->
+ let i1, i2 = get_int2 evd args in
+ let (h, l) = Uint63.mulc i1 i2 in
+ E.mkIntPair env (E.mkInt env h) (E.mkInt env l)
+ | Int63diveucl ->
+ let i1, i2 = get_int2 evd args in
+ let q,r = Uint63.div i1 i2, Uint63.rem i1 i2 in
+ E.mkIntPair env (E.mkInt env q) (E.mkInt env r)
+ | Int63div21 ->
+ let i1, i2, i3 = get_int3 evd args in
+ let q,r = Uint63.div21 i1 i2 i3 in
+ E.mkIntPair env (E.mkInt env q) (E.mkInt env r)
+ | Int63addMulDiv ->
+ let p, i, j = get_int3 evd args in
+ E.mkInt env
+ (Uint63.l_or
+ (Uint63.l_sl i p)
+ (Uint63.l_sr j (Uint63.sub (Uint63.of_int Uint63.uint_size) p)))
+ | Int63eq ->
+ let i1, i2 = get_int2 evd args in
+ E.mkBool env (Uint63.equal i1 i2)
+ | Int63lt ->
+ let i1, i2 = get_int2 evd args in
+ E.mkBool env (Uint63.lt i1 i2)
+ | Int63le ->
+ let i1, i2 = get_int2 evd args in
+ E.mkBool env (Uint63.le i1 i2)
+ | Int63compare ->
+ let i1, i2 = get_int2 evd args in
+ begin match Uint63.compare i1 i2 with
+ | x when x < 0 -> E.mkLt env
+ | 0 -> E.mkEq env
+ | _ -> E.mkGt env
+ end
+
+ let red_prim env evd p args =
+ try
+ let r =
+ red_prim_aux env evd p args
+ in Some r
+ with NativeDestKO -> None
+
+end
diff --git a/kernel/primred.mli b/kernel/primred.mli
new file mode 100644
index 0000000000..f5998982d7
--- /dev/null
+++ b/kernel/primred.mli
@@ -0,0 +1,44 @@
+open Names
+open Environ
+
+(** {5 Reduction of primitives} *)
+val add_retroknowledge : env -> Retroknowledge.action -> env
+
+val get_int_type : env -> Constant.t
+val get_bool_constructors : env -> constructor * constructor
+val get_carry_constructors : env -> constructor * constructor
+val get_pair_constructor : env -> constructor
+val get_cmp_constructors : env -> constructor * constructor * constructor
+
+exception NativeDestKO (* Should be raised by get_* functions on failure *)
+
+module type RedNativeEntries =
+ sig
+ type elem
+ type args
+ type evd (* will be unit in kernel, evar_map outside *)
+
+ val get : args -> int -> elem
+ val get_int : evd -> elem -> Uint63.t
+ val mkInt : env -> Uint63.t -> elem
+ val mkBool : env -> bool -> elem
+ val mkCarry : env -> bool -> elem -> elem (* true if carry *)
+ val mkIntPair : env -> elem -> elem -> elem
+ val mkLt : env -> elem
+ val mkEq : env -> elem
+ val mkGt : env -> elem
+ end
+
+module type RedNative =
+ sig
+ type elem
+ type args
+ type evd
+ val red_prim : env -> evd -> CPrimitives.t -> args -> elem option
+ end
+
+module RedNative :
+ functor (E:RedNativeEntries) ->
+ RedNative with type elem = E.elem
+ with type args = E.args
+ with type evd = E.evd
diff --git a/kernel/reduction.ml b/kernel/reduction.ml
index 97cd4c00d7..61051c001d 100644
--- a/kernel/reduction.ml
+++ b/kernel/reduction.ml
@@ -21,6 +21,7 @@ open CErrors
open Util
open Names
open Constr
+open Declarations
open Vars
open Environ
open CClosure
@@ -59,16 +60,23 @@ let compare_stack_shape stk1 stk2 =
Int.equal bal 0 (* && c1.ci_ind = c2.ci_ind *) && compare_rec 0 s1 s2
| (Zfix(_,a1)::s1, Zfix(_,a2)::s2) ->
Int.equal bal 0 && compare_rec 0 a1 a2 && compare_rec 0 s1 s2
+ | Zprimitive(op1,_,rargs1, _kargs1)::s1, Zprimitive(op2,_,rargs2, _kargs2)::s2 ->
+ bal=0 && op1=op2 && List.length rargs1=List.length rargs2 &&
+ compare_rec 0 s1 s2
| [], _ :: _
- | (Zproj _ | ZcaseT _ | Zfix _) :: _, _ -> false
+ | (Zproj _ | ZcaseT _ | Zfix _ | Zprimitive _) :: _, _ -> false
in
compare_rec 0 stk1 stk2
+type lft_fconstr = lift * fconstr
+
type lft_constr_stack_elt =
Zlapp of (lift * fconstr) array
| Zlproj of Projection.Repr.t * lift
| Zlfix of (lift * fconstr) * lft_constr_stack
| Zlcase of case_info * lift * constr * constr array * fconstr subs
+ | Zlprimitive of
+ CPrimitives.t * pconstant * lft_fconstr list * lft_fconstr next_native_args
and lft_constr_stack = lft_constr_stack_elt list
let rec zlapp v = function
@@ -102,7 +110,10 @@ let pure_stack lfts stk =
let (lfx,pa) = pure_rec l a in
(l, Zlfix((lfx,fx),pa)::pstk)
| (ZcaseT(ci,p,br,e),(l,pstk)) ->
- (l,Zlcase(ci,l,p,br,e)::pstk))
+ (l,Zlcase(ci,l,p,br,e)::pstk)
+ | (Zprimitive(op,c,rargs,kargs),(l,pstk)) ->
+ (l,Zlprimitive(op,c,List.map (fun t -> (l,t)) rargs,
+ List.map (fun (k,t) -> (k,(l,t))) kargs)::pstk))
in
snd (pure_rec lfts stk)
@@ -127,10 +138,10 @@ let nf_betaiota env t =
let whd_betaiotazeta env x =
match kind x with
| (Sort _|Var _|Meta _|Evar _|Const _|Ind _|Construct _|
- Prod _|Lambda _|Fix _|CoFix _) -> x
+ Prod _|Lambda _|Fix _|CoFix _|Int _) -> x
| App (c, _) ->
begin match kind c with
- | Ind _ | Construct _ | Evar _ | Meta _ | Const _ -> x
+ | Ind _ | Construct _ | Evar _ | Meta _ | Const _ | Int _ -> x
| Sort _ | Rel _ | Var _ | Cast _ | Prod _ | Lambda _ | LetIn _ | App _
| Case _ | Fix _ | CoFix _ | Proj _ ->
whd_val (create_clos_infos betaiotazeta env) (create_tab ()) (inject x)
@@ -141,10 +152,10 @@ let whd_betaiotazeta env x =
let whd_all env t =
match kind t with
| (Sort _|Meta _|Evar _|Ind _|Construct _|
- Prod _|Lambda _|Fix _|CoFix _) -> t
+ Prod _|Lambda _|Fix _|CoFix _|Int _) -> t
| App (c, _) ->
begin match kind c with
- | Ind _ | Construct _ | Evar _ | Meta _ -> t
+ | Ind _ | Construct _ | Evar _ | Meta _ | Int _ -> t
| Sort _ | Rel _ | Var _ | Cast _ | Prod _ | Lambda _ | LetIn _ | App _
| Const _ |Case _ | Fix _ | CoFix _ | Proj _ ->
whd_val (create_clos_infos all env) (create_tab ()) (inject t)
@@ -155,10 +166,10 @@ let whd_all env t =
let whd_allnolet env t =
match kind t with
| (Sort _|Meta _|Evar _|Ind _|Construct _|
- Prod _|Lambda _|Fix _|CoFix _|LetIn _) -> t
+ Prod _|Lambda _|Fix _|CoFix _|LetIn _|Int _) -> t
| App (c, _) ->
begin match kind c with
- | Ind _ | Construct _ | Evar _ | Meta _ | LetIn _ -> t
+ | Ind _ | Construct _ | Evar _ | Meta _ | LetIn _ | Int _ -> t
| Sort _ | Rel _ | Var _ | Cast _ | Prod _ | Lambda _ | App _
| Const _ | Case _ | Fix _ | CoFix _ | Proj _ ->
whd_val (create_clos_infos allnolet env) (create_tab ()) (inject t)
@@ -296,6 +307,15 @@ let rec skip_pattern n c =
| Lambda (_, _, c) -> skip_pattern (pred n) c
| _ -> raise IrregularPatternShape
+let unfold_ref_with_args infos tab fl v =
+ match unfold_reference infos tab fl with
+ | Def def -> Some (def, 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)))
+ | Undef _ | OpaqueDef _ | Primitive _ -> None
+
type conv_tab = {
cnv_inf : clos_infos;
lft_tab : clos_tab;
@@ -355,28 +375,26 @@ 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
- convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ let cuniv = conv_table_key infos.cnv_inf 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 *)
+ (* 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
- match unfold_reference infos.cnv_inf infos.lft_tab fl1 with
- | Some def1 -> ((lft1, (def1, v1)), appr2)
- | None ->
- (match unfold_reference infos.cnv_inf infos.rgt_tab fl2 with
- | Some def2 -> (appr1, (lft2, (def2, v2)))
- | None -> raise NotConvertible)
+ aux appr1 lft1 fl1 infos.lft_tab v1 appr2 lft2 fl2 infos.rgt_tab v2
else
- match unfold_reference infos.cnv_inf infos.rgt_tab fl2 with
- | Some def2 -> (appr1, (lft2, (def2, v2)))
- | None ->
- (match unfold_reference infos.cnv_inf infos.lft_tab fl1 with
- | Some def1 -> ((lft1, (def1, v1)), appr2)
- | None -> raise NotConvertible)
- in
- eqappr cv_pb l2r infos app1 app2 cuniv)
+ 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)
| (FProj (p1,c1), FProj (p2, c2)) ->
(* Projections: prefer unfolding to first-order unification,
@@ -400,31 +418,37 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
raise NotConvertible)
| (FProj (p1,c1), t2) ->
- (match unfold_projection infos.cnv_inf p1 with
- | Some s1 ->
+ begin match unfold_projection infos.cnv_inf p1 with
+ | Some s1 ->
eqappr cv_pb l2r infos (lft1, (c1, (s1 :: v1))) appr2 cuniv
- | None ->
- (match t2 with
- | FFlex fl2 ->
- (match unfold_reference infos.cnv_inf infos.rgt_tab fl2 with
- | Some def2 ->
- eqappr cv_pb l2r infos appr1 (lft2, (def2, v2)) cuniv
- | None -> raise NotConvertible)
- | _ -> raise NotConvertible))
-
+ | None ->
+ begin match t2 with
+ | FFlex fl2 ->
+ begin match unfold_ref_with_args infos.cnv_inf infos.rgt_tab fl2 v2 with
+ | Some t2 ->
+ eqappr cv_pb l2r infos appr1 (lft2, t2) cuniv
+ | None -> raise NotConvertible
+ end
+ | _ -> raise NotConvertible
+ end
+ end
+
| (t1, FProj (p2,c2)) ->
- (match unfold_projection infos.cnv_inf p2 with
- | Some s2 ->
+ begin match unfold_projection infos.cnv_inf p2 with
+ | Some s2 ->
eqappr cv_pb l2r infos appr1 (lft2, (c2, (s2 :: v2))) cuniv
- | None ->
- (match t1 with
- | FFlex fl1 ->
- (match unfold_reference infos.cnv_inf infos.lft_tab fl1 with
- | Some def1 ->
- eqappr cv_pb l2r infos (lft1, (def1, v1)) appr2 cuniv
- | None -> raise NotConvertible)
- | _ -> raise NotConvertible))
-
+ | None ->
+ begin match t1 with
+ | FFlex fl1 ->
+ begin match unfold_ref_with_args infos.cnv_inf infos.lft_tab fl1 v1 with
+ | Some t1 ->
+ eqappr cv_pb l2r infos (lft1, t1) appr2 cuniv
+ | None -> raise NotConvertible
+ end
+ | _ -> raise NotConvertible
+ end
+ end
+
(* other constructors *)
| (FLambda _, FLambda _) ->
(* Inconsistency: we tolerate that v1, v2 contain shift and update but
@@ -469,8 +493,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
(* only one constant, defined var or defined rel *)
| (FFlex fl1, c2) ->
- (match unfold_reference infos.cnv_inf infos.lft_tab fl1 with
- | Some def1 ->
+ begin match unfold_ref_with_args infos.cnv_inf infos.lft_tab fl1 v1 with
+ | Some (def1,v1) ->
(** By virtue of the previous case analyses, we know [c2] is rigid.
Conversion check to rigid terms eventually implies full weak-head
reduction, so instead of repeatedly performing small-step
@@ -478,32 +502,34 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
let all = RedFlags.red_add_transparent all (RedFlags.red_transparent (info_flags infos.cnv_inf)) in
let r1 = whd_stack (infos_with_reds infos.cnv_inf all) infos.lft_tab def1 v1 in
eqappr cv_pb l2r infos (lft1, r1) appr2 cuniv
- | None ->
- match c2 with
+ | None ->
+ (match c2 with
| FConstruct ((ind2,_j2),_u2) ->
- (try
- let v2, v1 =
- eta_expand_ind_stack (info_env infos.cnv_inf) ind2 hd2 v2 (snd appr1)
- in convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
- with Not_found -> raise NotConvertible)
- | _ -> raise NotConvertible)
-
+ (try
+ let v2, v1 =
+ eta_expand_ind_stack (info_env infos.cnv_inf) ind2 hd2 v2 (snd appr1)
+ in convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ with Not_found -> raise NotConvertible)
+ | _ -> raise NotConvertible)
+ end
+
| (c1, FFlex fl2) ->
- (match unfold_reference infos.cnv_inf infos.rgt_tab fl2 with
- | Some def2 ->
+ begin match unfold_ref_with_args infos.cnv_inf infos.rgt_tab fl2 v2 with
+ | Some (def2, v2) ->
(** Symmetrical case of above. *)
let all = RedFlags.red_add_transparent all (RedFlags.red_transparent (info_flags infos.cnv_inf)) in
let r2 = whd_stack (infos_with_reds infos.cnv_inf all) infos.rgt_tab def2 v2 in
eqappr cv_pb l2r infos appr1 (lft2, r2) cuniv
- | None ->
- match c1 with
- | FConstruct ((ind1,_j1),_u1) ->
- (try let v1, v2 =
- eta_expand_ind_stack (info_env infos.cnv_inf) ind1 hd1 v1 (snd appr2)
- in convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
- with Not_found -> raise NotConvertible)
- | _ -> raise NotConvertible)
-
+ | None ->
+ match c1 with
+ | FConstruct ((ind1,_j1),_u1) ->
+ (try let v1, v2 =
+ eta_expand_ind_stack (info_env infos.cnv_inf) ind1 hd1 v1 (snd appr2)
+ in convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ with Not_found -> raise NotConvertible)
+ | _ -> raise NotConvertible
+ end
+
(* Inductive types: MutInd MutConstruct Fix Cofix *)
| (FInd (ind1,u1), FInd (ind2,u2)) ->
if eq_ind ind1 ind2 then
@@ -584,13 +610,17 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
else raise NotConvertible
+ | FInt i1, FInt i2 ->
+ if Uint63.equal i1 i2 then convert_stacks l2r infos lft1 lft2 v1 v2 cuniv
+ else raise NotConvertible
+
(* Should not happen because both (hd1,v1) and (hd2,v2) are in whnf *)
| ( (FLetIn _, _) | (FCaseT _,_) | (FApp _,_) | (FCLOS _,_) | (FLIFT _,_)
| (_, FLetIn _) | (_,FCaseT _) | (_,FApp _) | (_,FCLOS _) | (_,FLIFT _)
| (FLOCKED,_) | (_,FLOCKED) ) -> assert false
| (FRel _ | FAtom _ | FInd _ | FFix _ | FCoFix _
- | FProd _ | FEvar _), _ -> raise NotConvertible
+ | FProd _ | FEvar _ | FInt _), _ -> raise NotConvertible
and convert_stacks l2r infos lft1 lft2 stk1 stk2 cuniv =
let f (l1, t1) (l2, t2) cuniv = ccnv CONV l2r infos l1 l2 t1 t2 cuniv in
@@ -613,7 +643,12 @@ and convert_stacks l2r infos lft1 lft2 stk1 stk2 cuniv =
raise NotConvertible;
let cu2 = f (l1, mk_clos e1 p1) (l2, mk_clos e2 p2) cu1 in
convert_branches l2r infos ci1 e1 e2 l1 l2 br1 br2 cu2
- | _ -> assert false)
+ | (Zlprimitive(op1,_,rargs1,kargs1),Zlprimitive(op2,_,rargs2,kargs2)) ->
+ if not (CPrimitives.equal op1 op2) then raise NotConvertible else
+ let cu2 = List.fold_right2 f rargs1 rargs2 cu1 in
+ let fk (_,a1) (_,a2) cu = f a1 a2 cu in
+ List.fold_right2 fk kargs1 kargs2 cu2
+ | ((Zlapp _ | Zlproj _ | Zlfix _| Zlcase _| Zlprimitive _), _) -> assert false)
| _ -> cuniv in
if compare_stack_shape stk1 stk2 then
cmp_rec (pure_stack lft1 stk1) (pure_stack lft2 stk2) cuniv
diff --git a/kernel/retroknowledge.ml b/kernel/retroknowledge.ml
index e51c25c06b..18fafdb6d3 100644
--- a/kernel/retroknowledge.ml
+++ b/kernel/retroknowledge.ml
@@ -12,249 +12,30 @@
(* Addition of native Head (nb of heading 0) and Tail (nb of trailing 0) by
Benjamin Grégoire, Jun 2007 *)
-(* This file defines the knowledge that the kernel is able to optimize
- for evaluation in the bytecode virtual machine *)
+(* This file defines the knowledge that the kernel is able to optimize. *)
open Names
-open Constr
-
-(* The retroknowledge defines a bijective correspondance between some
- [entry]-s (which are, in fact, merely names) and [field]-s which
- are roles assigned to these entries. *)
-
-type int31_field =
- | Int31Bits
- | Int31Type
- | Int31Constructor
- | Int31Twice
- | Int31TwicePlusOne
- | Int31Phi
- | Int31PhiInv
- | Int31Plus
- | Int31PlusC
- | Int31PlusCarryC
- | Int31Minus
- | Int31MinusC
- | Int31MinusCarryC
- | Int31Times
- | Int31TimesC
- | Int31Div21
- | Int31Div
- | Int31Diveucl
- | Int31AddMulDiv
- | Int31Compare
- | Int31Head0
- | Int31Tail0
- | Int31Lor
- | Int31Land
- | Int31Lxor
-
-type field =
- | KInt31 of int31_field
-
-let int31_field_of_string =
- function
- | "bits" -> Int31Bits
- | "type" -> Int31Type
- | "twice" -> Int31Twice
- | "twice_plus_one" -> Int31TwicePlusOne
- | "phi" -> Int31Phi
- | "phi_inv" -> Int31PhiInv
- | "plus" -> Int31Plus
- | "plusc" -> Int31PlusC
- | "pluscarryc" -> Int31PlusCarryC
- | "minus" -> Int31Minus
- | "minusc" -> Int31MinusC
- | "minuscarryc" -> Int31MinusCarryC
- | "times" -> Int31Times
- | "timesc" -> Int31TimesC
- | "div21" -> Int31Div21
- | "div" -> Int31Div
- | "diveucl" -> Int31Diveucl
- | "addmuldiv" -> Int31AddMulDiv
- | "compare" -> Int31Compare
- | "head0" -> Int31Head0
- | "tail0" -> Int31Tail0
- | "lor" -> Int31Lor
- | "land" -> Int31Land
- | "lxor" -> Int31Lxor
- | s -> CErrors.user_err Pp.(str "Registering unknown int31 operator " ++ str s)
-
-let int31_path = DirPath.make [ Id.of_string "int31" ]
-
-(* record representing all the flags of the internal state of the kernel *)
-type flags = {fastcomputation : bool}
-
-
-
-
-
-(* The [proactive] knowledge contains the mapping [field->entry]. *)
-
-module Proactive =
- Map.Make (struct type t = field let compare = Pervasives.compare end)
-
-type proactive = GlobRef.t Proactive.t
-
-(* The [reactive] knowledge contains the mapping
- [entry->field]. Fields are later to be interpreted as a
- [reactive_info]. *)
-
-module Reactive = GlobRef.Map
-
-type reactive_info = {(*information required by the compiler of the VM *)
- vm_compiling :
- (*fastcomputation flag -> continuation -> result *)
- (bool -> Cinstr.lambda array -> Cinstr.lambda)
- option;
- vm_constant_static :
- (*fastcomputation flag -> constructor -> args -> result*)
- (bool -> constr array -> Cinstr.lambda)
- option;
- vm_constant_dynamic :
- (*fastcomputation flag -> constructor -> reloc -> args -> sz -> cont -> result *)
- (bool -> Cinstr.lambda array -> Cinstr.lambda)
- option;
- (* fastcomputation flag -> cont -> result *)
- vm_before_match : (bool -> Cinstr.lambda -> Cinstr.lambda) option;
- (* tag (= compiled int for instance) -> result *)
- vm_decompile_const : (int -> constr) option;
-
- native_compiling :
- (bool -> Nativeinstr.prefix -> Nativeinstr.lambda array ->
- Nativeinstr.lambda) option;
-
- native_constant_static :
- (bool -> constr array -> Nativeinstr.lambda) option;
-
- native_constant_dynamic :
- (bool -> Nativeinstr.prefix -> constructor ->
- Nativeinstr.lambda array -> Nativeinstr.lambda) option;
-
- native_before_match : (bool -> Nativeinstr.prefix -> constructor ->
- Nativeinstr.lambda -> Nativeinstr.lambda) option
+type retroknowledge = {
+ retro_int63 : Constant.t option;
+ retro_bool : (constructor * constructor) option; (* true, false *)
+ retro_carry : (constructor * constructor) option; (* C0, C1 *)
+ retro_pair : constructor option;
+ retro_cmp : (constructor * constructor * constructor) option;
+ (* Eq, Lt, Gt *)
+ retro_refl : constructor option;
}
+let empty = {
+ retro_int63 = None;
+ retro_bool = None;
+ retro_carry = None;
+ retro_pair = None;
+ retro_cmp = None;
+ retro_refl = None;
+}
-
-and reactive = field Reactive.t
-
-and retroknowledge = {flags : flags; proactive : proactive; reactive : reactive}
-
-(* This type represent an atomic action of the retroknowledge. It
- is stored in the compiled libraries *)
-(* As per now, there is only the possibility of registering things
- the possibility of unregistering or changing the flag is under study *)
type action =
- | RKRegister of field * GlobRef.t
-
-
-(*initialisation*)
-let initial_flags =
- {fastcomputation = true;}
-
-let initial_proactive =
- (Proactive.empty:proactive)
-
-let initial_reactive =
- (Reactive.empty:reactive)
-
-let initial_retroknowledge =
- {flags = initial_flags;
- proactive = initial_proactive;
- reactive = initial_reactive }
-
-let empty_reactive_info =
- { vm_compiling = None ;
- vm_constant_static = None;
- vm_constant_dynamic = None;
- vm_before_match = None;
- vm_decompile_const = None;
- native_compiling = None;
- native_constant_static = None;
- native_constant_dynamic = None;
- native_before_match = None;
- }
-
-
-
-(* adds a binding [entry<->field]. *)
-let add_field knowledge field entry =
- {knowledge with
- proactive = Proactive.add field entry knowledge.proactive;
- reactive = Reactive.add entry field knowledge.reactive}
-
-(* acces functions for proactive retroknowledge *)
-let mem knowledge field =
- Proactive.mem field knowledge.proactive
-
-let find knowledge field =
- Proactive.find field knowledge.proactive
-
-
-let (dispatch,dispatch_hook) = Hook.make ()
-
-let dispatch_reactive entry retroknowledge =
- Hook.get dispatch retroknowledge entry (Reactive.find entry retroknowledge.reactive)
-
-(*access functions for reactive retroknowledge*)
-
-(* used for compiling of functions (add, mult, etc..) *)
-let get_vm_compiling_info knowledge key =
- match (dispatch_reactive key knowledge).vm_compiling
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-(* used for compilation of fully applied constructors *)
-let get_vm_constant_static_info knowledge key =
- match (dispatch_reactive key knowledge).vm_constant_static
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-(* used for compilation of partially applied constructors *)
-let get_vm_constant_dynamic_info knowledge key =
- match (dispatch_reactive key knowledge).vm_constant_dynamic
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-let get_vm_before_match_info knowledge key =
- match (dispatch_reactive key knowledge).vm_before_match
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-let get_vm_decompile_constant_info knowledge key =
- match (dispatch_reactive key knowledge).vm_decompile_const
- with
- | None -> raise Not_found
- | Some f -> f
-
-let get_native_compiling_info knowledge key =
- match (dispatch_reactive key knowledge).native_compiling
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-(* used for compilation of fully applied constructors *)
-let get_native_constant_static_info knowledge key =
- match (dispatch_reactive key knowledge).native_constant_static
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-(* used for compilation of partially applied constructors *)
-let get_native_constant_dynamic_info knowledge key =
- match (dispatch_reactive key knowledge).native_constant_dynamic
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
-
-let get_native_before_match_info knowledge key =
- match (dispatch_reactive key knowledge).native_before_match
- with
- | None -> raise Not_found
- | Some f -> f knowledge.flags.fastcomputation
+ | Register_ind of CPrimitives.prim_ind * inductive
+ | Register_type of CPrimitives.prim_type * Constant.t
+ | Register_inline of Constant.t
diff --git a/kernel/retroknowledge.mli b/kernel/retroknowledge.mli
index 0a2ef5300e..1554fe88da 100644
--- a/kernel/retroknowledge.mli
+++ b/kernel/retroknowledge.mli
@@ -9,157 +9,20 @@
(************************************************************************)
open Names
-open Constr
-
-type retroknowledge
-
-(** the following types correspond to the different "things"
- the kernel can learn about.*)
-type int31_field =
- | Int31Bits
- | Int31Type
- | Int31Constructor
- | Int31Twice
- | Int31TwicePlusOne
- | Int31Phi
- | Int31PhiInv
- | Int31Plus
- | Int31PlusC
- | Int31PlusCarryC
- | Int31Minus
- | Int31MinusC
- | Int31MinusCarryC
- | Int31Times
- | Int31TimesC
- | Int31Div21
- | Int31Div
- | Int31Diveucl
- | Int31AddMulDiv
- | Int31Compare
- | Int31Head0
- | Int31Tail0
- | Int31Lor
- | Int31Land
- | Int31Lxor
-
-type field =
- | KInt31 of int31_field
-
-val int31_field_of_string : string -> int31_field
-
-val int31_path : DirPath.t
-
-(** This type represent an atomic action of the retroknowledge. It
- is stored in the compiled libraries
- As per now, there is only the possibility of registering things
- the possibility of unregistering or changing the flag is under study *)
-type action =
- | RKRegister of field * GlobRef.t
-
-
-(** initial value for retroknowledge *)
-val initial_retroknowledge : retroknowledge
-
-
-(** Given an identifier id (usually Const _)
- and the continuation cont of the bytecode compilation
- returns the compilation of id in cont if it has a specific treatment
- or raises Not_found if id should be compiled as usual *)
-val get_vm_compiling_info : retroknowledge -> GlobRef.t ->
- Cinstr.lambda array -> Cinstr.lambda
-(*Given an identifier id (usually Construct _)
- and its argument array, returns a function that tries an ad-hoc optimisated
- compilation (in the case of the 31-bit integers it means compiling them
- directly into an integer)
- raises Not_found if id should be compiled as usual, and expectingly
- CBytecodes.NotClosed if the term is not a closed constructor pattern
- (a constant for the compiler) *)
-val get_vm_constant_static_info : retroknowledge -> GlobRef.t ->
- constr array -> Cinstr.lambda
-
-(*Given an identifier id (usually Construct _ )
- its argument array and a continuation, returns the compiled version
- of id+args+cont when id has a specific treatment (in the case of
- 31-bit integers, that would be the dynamic compilation into integers)
- or raises Not_found if id should be compiled as usual *)
-val get_vm_constant_dynamic_info : retroknowledge -> GlobRef.t ->
- Cinstr.lambda array -> Cinstr.lambda
-
-(** Given a type identifier, this function is used before compiling a match
- over this type. In the case of 31-bit integers for instance, it is used
- to add the instruction sequence which would perform a dynamic decompilation
- in case the argument of the match is not in coq representation *)
-val get_vm_before_match_info : retroknowledge -> GlobRef.t -> Cinstr.lambda
- -> Cinstr.lambda
-
-(** Given a type identifier, this function is used by pretyping/vnorm.ml to
- recover the elements of that type from their compiled form if it's non
- standard (it is used (and can be used) only when the compiled form
- is not a block *)
-val get_vm_decompile_constant_info : retroknowledge -> GlobRef.t -> int -> constr
-
-
-val get_native_compiling_info : retroknowledge -> GlobRef.t -> Nativeinstr.prefix ->
- Nativeinstr.lambda array -> Nativeinstr.lambda
-
-val get_native_constant_static_info : retroknowledge -> GlobRef.t ->
- constr array -> Nativeinstr.lambda
-
-val get_native_constant_dynamic_info : retroknowledge -> GlobRef.t ->
- Nativeinstr.prefix -> constructor ->
- Nativeinstr.lambda array ->
- Nativeinstr.lambda
-
-val get_native_before_match_info : retroknowledge -> GlobRef.t ->
- Nativeinstr.prefix -> constructor ->
- Nativeinstr.lambda -> Nativeinstr.lambda
-
-
-(** the following functions are solely used in Environ and Safe_typing to implement
- the functions register and unregister (and mem) of Environ *)
-val add_field : retroknowledge -> field -> GlobRef.t -> retroknowledge
-val mem : retroknowledge -> field -> bool
-(* val remove : retroknowledge -> field -> retroknowledge *)
-val find : retroknowledge -> field -> GlobRef.t
-
-
-(** Dispatching type for the above [get_*] functions. *)
-type reactive_info = {(*information required by the compiler of the VM *)
- vm_compiling :
- (*fastcomputation flag -> continuation -> result *)
- (bool -> Cinstr.lambda array -> Cinstr.lambda)
- option;
- vm_constant_static :
- (*fastcomputation flag -> constructor -> args -> result*)
- (bool -> constr array -> Cinstr.lambda)
- option;
- vm_constant_dynamic :
- (*fastcomputation flag -> constructor -> reloc -> args -> sz -> cont -> result *)
- (bool -> Cinstr.lambda array -> Cinstr.lambda)
- option;
- (* fastcomputation flag -> cont -> result *)
- vm_before_match : (bool -> Cinstr.lambda -> Cinstr.lambda) option;
- (* tag (= compiled int for instance) -> result *)
- vm_decompile_const : (int -> constr) option;
-
- native_compiling :
- (bool -> Nativeinstr.prefix -> Nativeinstr.lambda array ->
- Nativeinstr.lambda) option;
-
- native_constant_static :
- (bool -> constr array -> Nativeinstr.lambda) option;
-
- native_constant_dynamic :
- (bool -> Nativeinstr.prefix -> constructor ->
- Nativeinstr.lambda array -> Nativeinstr.lambda) option;
-
- native_before_match : (bool -> Nativeinstr.prefix -> constructor ->
- Nativeinstr.lambda -> Nativeinstr.lambda) option
+type retroknowledge = {
+ retro_int63 : Constant.t option;
+ retro_bool : (constructor * constructor) option; (* true, false *)
+ retro_carry : (constructor * constructor) option; (* C0, C1 *)
+ retro_pair : constructor option;
+ retro_cmp : (constructor * constructor * constructor) option;
+ (* Eq, Lt, Gt *)
+ retro_refl : constructor option;
}
-val empty_reactive_info : reactive_info
+val empty : retroknowledge
-(** Hook to be set after the compiler are installed to dispatch fields
- into the above [get_*] functions. *)
-val dispatch_hook : (retroknowledge -> GlobRef.t -> field -> reactive_info) Hook.t
+type action =
+ | Register_ind of CPrimitives.prim_ind * inductive
+ | Register_type of CPrimitives.prim_type * Constant.t
+ | Register_inline of Constant.t
diff --git a/kernel/safe_typing.ml b/kernel/safe_typing.ml
index df9e253135..474ce3e871 100644
--- a/kernel/safe_typing.ml
+++ b/kernel/safe_typing.ml
@@ -59,10 +59,10 @@
etc.
*)
-open CErrors
open Util
open Names
open Declarations
+open Constr
open Context.Named.Declaration
module NamedDecl = Context.Named.Declaration
@@ -227,6 +227,7 @@ let check_engagement env expected_impredicative_set =
let get_opaque_body env cbo =
match cbo.const_body with
| Undef _ -> assert false
+ | Primitive _ -> assert false
| Def _ -> `Nothing
| OpaqueDef opaque ->
`Opaque
@@ -467,7 +468,7 @@ let globalize_constant_universes env cb =
| Monomorphic_const cstrs ->
Now (false, cstrs) ::
(match cb.const_body with
- | (Undef _ | Def _) -> []
+ | (Undef _ | Def _ | Primitive _) -> []
| OpaqueDef lc ->
match Opaqueproof.get_constraints (Environ.opaque_tables env) lc with
| None -> []
@@ -492,6 +493,11 @@ let constraints_of_sfb env sfb =
| SFBmodtype mtb -> [Now (false, mtb.mod_constraints)]
| SFBmodule mb -> [Now (false, mb.mod_constraints)]
+let add_retroknowledge pttc senv =
+ { senv with
+ env = Primred.add_retroknowledge senv.env pttc;
+ local_retroknowledge = pttc::senv.local_retroknowledge }
+
(** A generic function for adding a new field in a same environment.
It also performs the corresponding [add_constraints]. *)
@@ -809,6 +815,13 @@ let add_constant ~in_section l decl senv =
let cb = Term_typing.translate_recipe ~hcons:(not in_section) senv.env kn r in
if in_section then cb else Declareops.hcons_const_body cb in
add_constant_aux ~in_section senv (kn, cb) in
+ let senv =
+ match decl with
+ | ConstantEntry (_,(Entries.PrimitiveEntry { Entries.prim_entry_content = CPrimitives.OT_type t; _ })) ->
+ if in_section then CErrors.anomaly (Pp.str "Primitive type not allowed in sections");
+ add_retroknowledge (Retroknowledge.Register_type(t,kn)) senv
+ | _ -> senv
+ in
kn, senv
(** Insertion of inductive types *)
@@ -1173,18 +1186,6 @@ let typing senv = Typeops.infer (env_of_senv senv)
(** {6 Retroknowledge / native compiler } *)
-let register field value senv =
- (* todo : value closed *)
- (* spiwack : updates the safe_env with the information that the register
- action has to be performed (again) when the environment is imported *)
- { senv with
- env = Environ.register senv.env field value;
- local_retroknowledge =
- Retroknowledge.RKRegister (field,value)::senv.local_retroknowledge
- }
-
-(* This function serves only for inlining constants in native compiler for now,
-but it is meant to become a replacement for environ.register *)
let register_inline kn senv =
let open Environ in
if not (evaluable_constant kn senv.env) then
@@ -1194,6 +1195,80 @@ let register_inline kn senv =
let cb = {cb with const_inline_code = true} in
let env = add_constant kn cb env in { senv with env}
+let check_register_ind (mind,i) r env =
+ let mb = Environ.lookup_mind mind env in
+ let check_if b s =
+ if not b then
+ CErrors.user_err ~hdr:"check_register_ind" (Pp.str s) in
+ check_if (Int.equal (Array.length mb.mind_packets) 1) "A non mutual inductive is expected";
+ let ob = mb.mind_packets.(i) in
+ let check_nconstr n =
+ check_if (Int.equal (Array.length ob.mind_consnames) n)
+ ("an inductive type with "^(string_of_int n)^" constructors is expected")
+ in
+ let check_name pos s =
+ check_if (Id.equal ob.mind_consnames.(pos) (Id.of_string s))
+ ("the "^(string_of_int (pos + 1))^
+ "th constructor does not have the expected name: " ^ s) in
+ let check_type pos t =
+ check_if (Constr.equal t ob.mind_user_lc.(pos))
+ ("the "^(string_of_int (pos + 1))^
+ "th constructor does not have the expected type") in
+ let check_type_cte pos = check_type pos (Constr.mkRel 1) in
+ match r with
+ | CPrimitives.PIT_bool ->
+ check_nconstr 2;
+ check_name 0 "true";
+ check_type_cte 0;
+ check_name 1 "false";
+ check_type_cte 1
+ | CPrimitives.PIT_carry ->
+ check_nconstr 2;
+ let test_type pos =
+ let c = ob.mind_user_lc.(pos) in
+ let s = "the "^(string_of_int (pos + 1))^
+ "th constructor does not have the expected type" in
+ check_if (Constr.isProd c) s;
+ let (_,d,cd) = Constr.destProd c in
+ check_if (Constr.is_Type d) s;
+ check_if
+ (Constr.equal
+ (mkProd (Anonymous,mkRel 1, mkApp (mkRel 3,[|mkRel 2|])))
+ cd)
+ s in
+ check_name 0 "C0";
+ test_type 0;
+ check_name 1 "C1";
+ test_type 1;
+ | CPrimitives.PIT_pair ->
+ check_nconstr 1;
+ check_name 0 "pair";
+ let c = ob.mind_user_lc.(0) in
+ let s = "the "^(string_of_int 1)^
+ "th constructor does not have the expected type" in
+ begin match Term.decompose_prod c with
+ | ([_,b;_,a;_,_B;_,_A], codom) ->
+ check_if (is_Type _A) s;
+ check_if (is_Type _B) s;
+ check_if (Constr.equal a (mkRel 2)) s;
+ check_if (Constr.equal b (mkRel 2)) s;
+ check_if (Constr.equal codom (mkApp (mkRel 5,[|mkRel 4; mkRel 3|]))) s
+ | _ -> check_if false s
+ end
+ | CPrimitives.PIT_cmp ->
+ check_nconstr 3;
+ check_name 0 "Eq";
+ check_type_cte 0;
+ check_name 1 "Lt";
+ check_type_cte 1;
+ check_name 2 "Gt";
+ check_type_cte 2
+
+let register_inductive ind prim senv =
+ check_register_ind ind prim senv.env;
+ let action = Retroknowledge.Register_ind(prim,ind) in
+ add_retroknowledge action senv
+
let add_constraints c =
add_constraints
(Now (false, Univ.ContextSet.add_constraints c Univ.ContextSet.empty))
@@ -1222,125 +1297,3 @@ Would this be correct with respect to undo's and stuff ?
let set_strategy k l e = { e with env =
(Environ.set_oracle e.env
(Conv_oracle.set_strategy (Environ.oracle e.env) k l)) }
-
-(** Register retroknowledge hooks *)
-
-open Retroknowledge
-
-(* the Environ.register function synchronizes the proactive and reactive
- retroknowledge. *)
-let dispatch =
-
- (* subfunction used for static decompilation of int31 (after a vm_compute,
- see pretyping/vnorm.ml for more information) *)
- let constr_of_int31 =
- let nth_digit_plus_one i n = (* calculates the nth (starting with 0)
- digit of i and adds 1 to it
- (nth_digit_plus_one 1 3 = 2) *)
- if Int.equal (i land (1 lsl n)) 0 then
- 1
- else
- 2
- in
- fun ind -> fun digit_ind -> fun tag ->
- let array_of_int i =
- Array.init 31 (fun n -> Constr.mkConstruct
- (digit_ind, nth_digit_plus_one i (30-n)))
- in
- (* We check that no bit above 31 is set to one. This assertion used to
- fail in the VM, and led to conversion tests failing at Qed. *)
- assert (Int.equal (tag lsr 31) 0);
- Constr.mkApp(Constr.mkConstruct(ind, 1), array_of_int tag)
- in
-
- (* subfunction which dispatches the compiling information of an
- int31 operation which has a specific vm instruction (associates
- it to the name of the coq definition in the reactive retroknowledge) *)
- let int31_op n op prim kn =
- { empty_reactive_info with
- vm_compiling = Some (Clambda.compile_prim n op (kn, Univ.Instance.empty)); (*XXX: FIXME universes? *)
- native_compiling = Some (Nativelambda.compile_prim prim kn);
- }
- in
-
-fun rk value field ->
- (* subfunction which shortens the (very common) dispatch of operations *)
- let int31_op_from_const n op prim =
- match value with
- | GlobRef.ConstRef kn -> int31_op n op prim kn
- | _ -> anomaly ~label:"Environ.register" (Pp.str "should be a constant.")
- in
- let int31_binop_from_const op prim = int31_op_from_const 2 op prim in
- let int31_unop_from_const op prim = int31_op_from_const 1 op prim in
- match field with
- | KInt31 Int31Type ->
- let int31bit =
- (* invariant : the type of bits is registered, otherwise the function
- would raise Not_found. The invariant is enforced in safe_typing.ml *)
- match field with
- | KInt31 Int31Type -> Retroknowledge.find rk (KInt31 Int31Bits)
- | _ -> anomaly ~label:"Environ.register"
- (Pp.str "add_int31_decompilation_from_type called with an abnormal field.")
- in
- let i31bit_type =
- match int31bit with
- | GlobRef.IndRef i31bit_type -> i31bit_type
- | _ -> anomaly ~label:"Environ.register"
- (Pp.str "Int31Bits should be an inductive type.")
- in
- let int31_decompilation =
- match value with
- | GlobRef.IndRef i31t ->
- constr_of_int31 i31t i31bit_type
- | _ -> anomaly ~label:"Environ.register"
- (Pp.str "should be an inductive type.")
- in
- { empty_reactive_info with
- vm_decompile_const = Some int31_decompilation;
- vm_before_match = Some Clambda.int31_escape_before_match;
- native_before_match = Some (Nativelambda.before_match_int31 i31bit_type);
- }
- | KInt31 Int31Constructor ->
- { empty_reactive_info with
- vm_constant_static = Some Clambda.compile_structured_int31;
- vm_constant_dynamic = Some Clambda.dynamic_int31_compilation;
- native_constant_static = Some Nativelambda.compile_static_int31;
- native_constant_dynamic = Some Nativelambda.compile_dynamic_int31;
- }
- | KInt31 Int31Plus -> int31_binop_from_const Cbytecodes.Kaddint31
- CPrimitives.Int31add
- | KInt31 Int31PlusC -> int31_binop_from_const Cbytecodes.Kaddcint31
- CPrimitives.Int31addc
- | KInt31 Int31PlusCarryC -> int31_binop_from_const Cbytecodes.Kaddcarrycint31
- CPrimitives.Int31addcarryc
- | KInt31 Int31Minus -> int31_binop_from_const Cbytecodes.Ksubint31
- CPrimitives.Int31sub
- | KInt31 Int31MinusC -> int31_binop_from_const Cbytecodes.Ksubcint31
- CPrimitives.Int31subc
- | KInt31 Int31MinusCarryC -> int31_binop_from_const
- Cbytecodes.Ksubcarrycint31 CPrimitives.Int31subcarryc
- | KInt31 Int31Times -> int31_binop_from_const Cbytecodes.Kmulint31
- CPrimitives.Int31mul
- | KInt31 Int31TimesC -> int31_binop_from_const Cbytecodes.Kmulcint31
- CPrimitives.Int31mulc
- | KInt31 Int31Div21 -> int31_op_from_const 3 Cbytecodes.Kdiv21int31
- CPrimitives.Int31div21
- | KInt31 Int31Diveucl -> int31_binop_from_const Cbytecodes.Kdivint31
- CPrimitives.Int31diveucl
- | KInt31 Int31AddMulDiv -> int31_op_from_const 3 Cbytecodes.Kaddmuldivint31
- CPrimitives.Int31addmuldiv
- | KInt31 Int31Compare -> int31_binop_from_const Cbytecodes.Kcompareint31
- CPrimitives.Int31compare
- | KInt31 Int31Head0 -> int31_unop_from_const Cbytecodes.Khead0int31
- CPrimitives.Int31head0
- | KInt31 Int31Tail0 -> int31_unop_from_const Cbytecodes.Ktail0int31
- CPrimitives.Int31tail0
- | KInt31 Int31Lor -> int31_binop_from_const Cbytecodes.Klorint31
- CPrimitives.Int31lor
- | KInt31 Int31Land -> int31_binop_from_const Cbytecodes.Klandint31
- CPrimitives.Int31land
- | KInt31 Int31Lxor -> int31_binop_from_const Cbytecodes.Klxorint31
- CPrimitives.Int31lxor
- | _ -> empty_reactive_info
-
-let _ = Hook.set Retroknowledge.dispatch_hook dispatch
diff --git a/kernel/safe_typing.mli b/kernel/safe_typing.mli
index 57b01f15e3..1b7239da23 100644
--- a/kernel/safe_typing.mli
+++ b/kernel/safe_typing.mli
@@ -217,12 +217,8 @@ val mind_of_delta_kn_senv : safe_environment -> KerName.t -> MutInd.t
(** {6 Retroknowledge / Native compiler } *)
-open Retroknowledge
-
-val register :
- field -> GlobRef.t -> safe_transformer0
-
val register_inline : Constant.t -> safe_transformer0
+val register_inductive : inductive -> CPrimitives.prim_ind -> safe_transformer0
val set_strategy :
Names.Constant.t Names.tableKey -> Conv_oracle.level -> safe_transformer0
diff --git a/kernel/subtyping.ml b/kernel/subtyping.ml
index 347c30dd64..2fc3aa99b5 100644
--- a/kernel/subtyping.ml
+++ b/kernel/subtyping.ml
@@ -257,10 +257,10 @@ let check_constant cst env l info1 cb2 spec2 subst1 subst2 =
anything of the right type can implement it, even if bodies differ.
*)
(match cb2.const_body with
- | Undef _ | OpaqueDef _ -> cst
+ | Primitive _ | Undef _ | OpaqueDef _ -> cst
| Def lc2 ->
(match cb1.const_body with
- | Undef _ | OpaqueDef _ -> error NotConvertibleBodyField
+ | Primitive _ | Undef _ | OpaqueDef _ -> error NotConvertibleBodyField
| Def lc1 ->
(* NB: cb1 might have been strengthened and appear as transparent.
Anyway [check_conv] will handle that afterwards. *)
diff --git a/kernel/term.ml b/kernel/term.ml
index 795cdeb040..58b289eaa5 100644
--- a/kernel/term.ml
+++ b/kernel/term.ml
@@ -379,4 +379,4 @@ let kind_of_type t = match kind t with
| (Rel _ | Meta _ | Var _ | Evar _ | Const _
| Proj _ | Case _ | Fix _ | CoFix _ | Ind _)
-> AtomicType (t,[||])
- | (Lambda _ | Construct _) -> failwith "Not a type"
+ | (Lambda _ | Construct _ | Int _) -> failwith "Not a type"
diff --git a/kernel/term_typing.ml b/kernel/term_typing.ml
index f9fdbdd68e..3cb5d17d34 100644
--- a/kernel/term_typing.ml
+++ b/kernel/term_typing.ml
@@ -93,10 +93,45 @@ let infer_declaration (type a) ~(trust : a trust) env (dcl : a constant_entry) =
cook_context = ctx;
}
+ (** Primitives cannot be universe polymorphic *)
+ | PrimitiveEntry ({ prim_entry_type = otyp;
+ prim_entry_univs = uctxt;
+ prim_entry_content = op_t;
+ }) ->
+ let env = push_context_set ~strict:true uctxt env in
+ let ty = match otyp with
+ | Some typ ->
+ let tyj = infer_type env typ in
+ check_primitive_type env op_t tyj.utj_val;
+ Constr.hcons tyj.utj_val
+ | None ->
+ match op_t with
+ | CPrimitives.OT_op op -> type_of_prim env op
+ | CPrimitives.OT_type _ -> mkSet
+ in
+ let cd =
+ match op_t with
+ | CPrimitives.OT_op op -> Declarations.Primitive op
+ | CPrimitives.OT_type _ -> Undef None in
+ { Cooking.cook_body = cd;
+ cook_type = ty;
+ cook_universes = Monomorphic_const uctxt;
+ cook_private_univs = None;
+ cook_inline = false;
+ cook_context = None
+ }
+
(** Definition [c] is opaque (Qed), non polymorphic and with a specified type,
so we delay the typing and hash consing of its body.
Remark: when the universe quantification is given explicitly, we could
delay even in the polymorphic case. *)
+
+(** Definition is opaque (Qed) and non polymorphic with known type, so we delay
+the typing and hash consing of its body.
+
+TODO: if the universe quantification is given explicitly, we could delay even in
+the polymorphic case
+ *)
| DefinitionEntry ({ const_entry_type = Some typ;
const_entry_opaque = true;
const_entry_universes = Monomorphic_const_entry univs; _ } as c) ->
@@ -238,7 +273,7 @@ let build_constant_declaration _kn env result =
we must look at the body NOW, if any *)
let ids_typ = global_vars_set env typ in
let ids_def = match def with
- | Undef _ -> Id.Set.empty
+ | Undef _ | Primitive _ -> Id.Set.empty
| Def cs -> global_vars_set env (Mod_subst.force_constr cs)
| OpaqueDef lc ->
let vars =
@@ -258,7 +293,7 @@ let build_constant_declaration _kn env result =
(* We use the declared set and chain a check of correctness *)
sort declared,
match def with
- | Undef _ as x -> x (* nothing to check *)
+ | Undef _ | Primitive _ as x -> x (* nothing to check *)
| Def cs as x ->
let ids_typ = global_vars_set env typ in
let ids_def = global_vars_set env (Mod_subst.force_constr cs) in
@@ -316,6 +351,7 @@ let translate_local_def env _id centry =
if Option.is_empty decl.cook_context && !Flags.record_aux_file then begin
match decl.cook_body with
| Undef _ -> ()
+ | Primitive _ -> ()
| Def _ -> ()
| OpaqueDef lc ->
let ids_typ = global_vars_set env typ in
@@ -336,7 +372,7 @@ let translate_local_def env _id centry =
the body by virtue of the typing of [Entries.section_def_entry]. *)
let () = assert (Univ.ContextSet.is_empty cst) in
p
- | Undef _ -> assert false
+ | Undef _ | Primitive _ -> assert false
in
c, typ
diff --git a/kernel/typeops.ml b/kernel/typeops.ml
index c9acd168e8..7eb8e803b3 100644
--- a/kernel/typeops.ml
+++ b/kernel/typeops.ml
@@ -12,7 +12,7 @@ open CErrors
open Util
open Names
open Univ
-open Sorts
+open Term
open Constr
open Vars
open Declarations
@@ -187,6 +187,74 @@ let type_of_apply env func funt argsv argstv =
in
apply_rec 0 (inject funt)
+(* Type of primitive constructs *)
+let type_of_prim_type _env = function
+ | CPrimitives.PT_int63 -> Constr.mkSet
+
+let type_of_int env =
+ match env.retroknowledge.Retroknowledge.retro_int63 with
+ | Some c -> mkConst c
+ | None -> CErrors.user_err Pp.(str"The type int must be registered before this construction can be typechecked.")
+
+let type_of_prim env t =
+ let int_ty = type_of_int env in
+ let bool_ty () =
+ match env.retroknowledge.Retroknowledge.retro_bool with
+ | Some ((ind,_),_) -> Constr.mkInd ind
+ | None -> CErrors.user_err Pp.(str"The type bool must be registered before this primitive.")
+ in
+ let compare_ty () =
+ match env.retroknowledge.Retroknowledge.retro_cmp with
+ | Some ((ind,_),_,_) -> Constr.mkInd ind
+ | None -> CErrors.user_err Pp.(str"The type compare must be registered before this primitive.")
+ in
+ let pair_ty fst_ty snd_ty =
+ match env.retroknowledge.Retroknowledge.retro_pair with
+ | Some (ind,_) -> Constr.mkApp(Constr.mkInd ind, [|fst_ty;snd_ty|])
+ | None -> CErrors.user_err Pp.(str"The type pair must be registered before this primitive.")
+ in
+ let carry_ty int_ty =
+ match env.retroknowledge.Retroknowledge.retro_carry with
+ | Some ((ind,_),_) -> Constr.mkApp(Constr.mkInd ind, [|int_ty|])
+ | None -> CErrors.user_err Pp.(str"The type carry must be registered before this primitive.")
+ in
+ let rec nary_int63_op arity ty =
+ if Int.equal arity 0 then ty
+ else Constr.mkProd(Name (Id.of_string "x"), int_ty, nary_int63_op (arity-1) ty)
+ in
+ let return_ty =
+ let open CPrimitives in
+ match t with
+ | Int63head0
+ | Int63tail0
+ | Int63add
+ | Int63sub
+ | Int63mul
+ | Int63div
+ | Int63mod
+ | Int63lsr
+ | Int63lsl
+ | Int63land
+ | Int63lor
+ | Int63lxor
+ | Int63addMulDiv -> int_ty
+ | Int63eq
+ | Int63lt
+ | Int63le -> bool_ty ()
+ | Int63mulc
+ | Int63div21
+ | Int63diveucl -> pair_ty int_ty int_ty
+ | Int63addc
+ | Int63subc
+ | Int63addCarryC
+ | Int63subCarryC -> carry_ty int_ty
+ | Int63compare -> compare_ty ()
+ in
+ nary_int63_op (CPrimitives.arity t) return_ty
+
+let judge_of_int env i =
+ make_judge (Constr.mkInt i) (type_of_int env)
+
(* Type of product *)
let sort_of_product env domsort rangsort =
@@ -468,6 +536,9 @@ let rec execute env cstr =
let (fix_ty,recdef') = execute_recdef env recdef i in
let cofix = (i,recdef') in
check_cofix env cofix; fix_ty
+
+ (* Primitive types *)
+ | Int _ -> type_of_int env
(* Partial proofs: unsupported by the kernel *)
| Meta _ ->
@@ -590,3 +661,20 @@ let judge_of_case env ci pj cj lfj =
let lf, lft = dest_judgev lfj in
make_judge (mkCase (ci, (*nf_betaiota*) pj.uj_val, cj.uj_val, lft))
(type_of_case env ci pj.uj_val pj.uj_type cj.uj_val cj.uj_type lf lft)
+
+(* Building type of primitive operators and type *)
+
+open CPrimitives
+
+let check_primitive_type env op_t t =
+ match op_t with
+ | OT_type PT_int63 ->
+ (try
+ default_conv ~l2r:false CUMUL env mkSet t
+ with NotConvertible ->
+ CErrors.user_err Pp.(str"Was expecting the sort of this primitive type to be Set"))
+ | OT_op p ->
+ (try
+ default_conv ~l2r:false CUMUL env (type_of_prim env p) t
+ with NotConvertible ->
+ CErrors.user_err Pp.(str"Not the expected type for this primitive"))
diff --git a/kernel/typeops.mli b/kernel/typeops.mli
index 4193324136..52c261c5e8 100644
--- a/kernel/typeops.mli
+++ b/kernel/typeops.mli
@@ -118,3 +118,13 @@ val constr_of_global_in_context : env -> GlobRef.t -> types * Univ.AUContext.t
(** Check that hyps are included in env and fails with error otherwise *)
val check_hyps_inclusion : env -> ?evars:((existential->constr option) * UGraph.t) ->
('a -> constr) -> 'a -> Constr.named_context -> unit
+
+val check_primitive_type : env -> CPrimitives.op_or_type -> types -> unit
+
+(** Types for primitives *)
+
+val type_of_int : env -> types
+val judge_of_int : env -> Uint63.t -> unsafe_judgment
+
+val type_of_prim_type : env -> CPrimitives.prim_type -> types
+val type_of_prim : env -> CPrimitives.t -> types
diff --git a/kernel/uint31.ml b/kernel/uint31.ml
deleted file mode 100644
index d9c723c243..0000000000
--- a/kernel/uint31.ml
+++ /dev/null
@@ -1,153 +0,0 @@
- (* Invariant: For arch64 all extra bytes are set to 0 *)
-type t = int
-
- (* to be used only on 32 bits architectures *)
-let maxuint31 = Int32.of_string "0x7FFFFFFF"
-let uint_32 i = Int32.logand (Int32.of_int i) maxuint31
-
-let select f32 f64 = if Sys.word_size = 64 then f64 else f32
-
- (* conversion to an int *)
-let to_int i = i
-
-let of_int_32 i = i
-let of_int_64 i = i land 0x7FFFFFFF
-
-let of_int = select of_int_32 of_int_64
-let of_uint i = i
-
- (* conversion of an uint31 to a string *)
-let to_string_32 i = Int32.to_string (uint_32 i)
-let to_string_64 = string_of_int
-
-let to_string = select to_string_32 to_string_64
-let of_string s =
- let i32 = Int32.of_string s in
- if Int32.compare Int32.zero i32 <= 0
- && Int32.compare i32 maxuint31 <= 0
- then Int32.to_int i32
- else raise (Failure "int_of_string")
-
-
-
- (* logical shift *)
-let l_sl x y =
- of_int (if 0 <= y && y < 31 then x lsl y else 0)
-
-let l_sr x y =
- if 0 <= y && y < 31 then x lsr y else 0
-
-let l_and x y = x land y
-let l_or x y = x lor y
-let l_xor x y = x lxor y
-
- (* addition of int31 *)
-let add x y = of_int (x + y)
-
- (* subtraction *)
-let sub x y = of_int (x - y)
-
- (* multiplication *)
-let mul x y = of_int (x * y)
-
- (* exact multiplication *)
-let mulc_32 x y =
- let x = Int64.of_int32 (uint_32 x) in
- let y = Int64.of_int32 (uint_32 y) in
- let m = Int64.mul x y in
- let l = Int64.to_int m in
- let h = Int64.to_int (Int64.shift_right_logical m 31) in
- h,l
-
-let mulc_64 x y =
- let m = x * y in
- let l = of_int_64 m in
- let h = of_int_64 (m lsr 31) in
- h, l
-let mulc = select mulc_32 mulc_64
-
- (* division *)
-let div_32 x y =
- if y = 0 then 0 else
- Int32.to_int (Int32.div (uint_32 x) (uint_32 y))
-let div_64 x y = if y = 0 then 0 else x / y
-let div = select div_32 div_64
-
- (* modulo *)
-let rem_32 x y =
- if y = 0 then 0
- else Int32.to_int (Int32.rem (uint_32 x) (uint_32 y))
-let rem_64 x y = if y = 0 then 0 else x mod y
-let rem = select rem_32 rem_64
-
- (* division of two numbers by one *)
-let div21_32 xh xl y =
- if y = 0 then (0,0)
- else
- let x =
- Int64.logor
- (Int64.shift_left (Int64.of_int32 (uint_32 xh)) 31)
- (Int64.of_int32 (uint_32 xl)) in
- let y = Int64.of_int32 (uint_32 y) in
- let q = Int64.div x y in
- let r = Int64.rem x y in
- Int64.to_int q, Int64.to_int r
-let div21_64 xh xl y =
- if y = 0 then (0,0)
- else
- let x = (xh lsl 31) lor xl in
- let q = x / y in
- let r = x mod y in
- q, r
-let div21 = select div21_32 div21_64
-
- (* comparison *)
-let lt_32 x y = (x lxor 0x40000000) < (y lxor 0x40000000)
-
-(* Do not remove the type information it is really important for
- efficiency *)
-let lt_64 (x:int) (y:int) = x < y
-let lt = select lt_32 lt_64
-
-let le_32 x y =
- (x lxor 0x40000000) <= (y lxor 0x40000000)
-
-(* Do not remove the type information it is really important for
- efficiency *)
-let le_64 (x:int) (y:int) = x <= y
-let le = select le_32 le_64
-
-let equal (x:int) (y:int) = x == y
-
-let cmp_32 x y = Int32.compare (uint_32 x) (uint_32 y)
-(* Do not remove the type information it is really important for
- efficiency *)
-let cmp_64 (x:int) (y:int) = compare x y
-let compare = select cmp_32 cmp_64
-
- (* head tail *)
-
-let head0 x =
- let r = ref 0 in
- let x = ref x in
- if !x land 0x7FFF0000 = 0 then r := !r + 15
- else x := !x lsr 15;
- if !x land 0xFF00 = 0 then (x := !x lsl 8; r := !r + 8);
- if !x land 0xF000 = 0 then (x := !x lsl 4; r := !r + 4);
- if !x land 0xC000 = 0 then (x := !x lsl 2; r := !r + 2);
- if !x land 0x8000 = 0 then (x := !x lsl 1; r := !r + 1);
- if !x land 0x8000 = 0 then ( r := !r + 1);
- !r;;
-
-let tail0 x =
- let r = ref 0 in
- let x = ref x in
- if !x land 0xFFFF = 0 then (x := !x lsr 16; r := !r + 16);
- if !x land 0xFF = 0 then (x := !x lsr 8; r := !r + 8);
- if !x land 0xF = 0 then (x := !x lsr 4; r := !r + 4);
- if !x land 0x3 = 0 then (x := !x lsr 2; r := !r + 2);
- if !x land 0x1 = 0 then ( r := !r + 1);
- !r
-
-let add_digit x d =
- (x lsl 1) lor d
diff --git a/kernel/uint31.mli b/kernel/uint63.mli
index d1f933cc4e..b5f40ca804 100644
--- a/kernel/uint31.mli
+++ b/kernel/uint63.mli
@@ -1,14 +1,28 @@
type t
+val uint_size : int
+val maxuint31 : t
+
(* conversion to int *)
-val to_int : t -> int
val of_int : int -> t
+val to_int2 : t -> int * int (* msb, lsb *)
+val of_int64 : Int64.t -> t
+(*
val of_uint : int -> t
+*)
+
+val hash : t -> int
- (* conversion to a string *)
+ (* convertion to a string *)
val to_string : t -> string
val of_string : string -> t
+val compile : t -> string
+
+(* constants *)
+val zero : t
+val one : t
+
(* logical operations *)
val l_sl : t -> t -> t
val l_sr : t -> t -> t
@@ -16,20 +30,21 @@ val l_and : t -> t -> t
val l_xor : t -> t -> t
val l_or : t -> t -> t
- (* Arithmetic operations *)
+ (* Arithmetic operations *)
val add : t -> t -> t
val sub : t -> t -> t
val mul : t -> t -> t
val div : t -> t -> t
val rem : t -> t -> t
-
+
(* Specific arithmetic operations *)
val mulc : t -> t -> t * t
+val addmuldiv : t -> t -> t -> t
val div21 : t -> t -> t -> t * t
-
+
(* comparison *)
val lt : t -> t -> bool
-val equal : t -> t -> bool
+val equal : t -> t -> bool
val le : t -> t -> bool
val compare : t -> t -> int
@@ -37,5 +52,4 @@ val compare : t -> t -> int
val head0 : t -> t
val tail0 : t -> t
-(** Used by retroknowledge *)
-val add_digit : t -> t -> t
+val is_uint63 : Obj.t -> bool
diff --git a/kernel/uint63_amd64.ml b/kernel/uint63_amd64.ml
new file mode 100644
index 0000000000..010b594de8
--- /dev/null
+++ b/kernel/uint63_amd64.ml
@@ -0,0 +1,215 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+type t = int
+
+let _ = assert (Sys.word_size = 64)
+
+let uint_size = 63
+
+let maxuint63 = Int64.of_string "0x7FFFFFFFFFFFFFFF"
+let maxuint31 = 0x7FFFFFFF
+
+ (* conversion from an int *)
+let to_uint64 i = Int64.logand (Int64.of_int i) maxuint63
+
+let of_int i = i
+[@@ocaml.inline always]
+
+let to_int2 i = (0,i)
+
+let of_int64 _i = assert false
+
+let hash i = i
+[@@ocaml.inline always]
+
+ (* conversion of an uint63 to a string *)
+let to_string i = Int64.to_string (to_uint64 i)
+
+let of_string s =
+ let i64 = Int64.of_string s in
+ if Int64.compare Int64.zero i64 <= 0
+ && Int64.compare i64 maxuint63 <= 0
+ then Int64.to_int i64
+ else raise (Failure "Int64.of_string")
+
+(* Compiles an unsigned int to OCaml code *)
+let compile i = Printf.sprintf "Uint63.of_int (%i)" i
+
+let zero = 0
+let one = 1
+
+ (* logical shift *)
+let l_sl x y =
+ if 0 <= y && y < 63 then x lsl y else 0
+
+let l_sr x y =
+ if 0 <= y && y < 63 then x lsr y else 0
+
+let l_and x y = x land y
+[@@ocaml.inline always]
+
+let l_or x y = x lor y
+[@@ocaml.inline always]
+
+let l_xor x y = x lxor y
+[@@ocaml.inline always]
+
+ (* addition of int63 *)
+let add x y = x + y
+[@@ocaml.inline always]
+
+ (* subtraction *)
+let sub x y = x - y
+[@@ocaml.inline always]
+
+ (* multiplication *)
+let mul x y = x * y
+[@@ocaml.inline always]
+
+ (* division *)
+let div (x : int) (y : int) =
+ if y = 0 then 0 else Int64.to_int (Int64.div (to_uint64 x) (to_uint64 y))
+
+ (* modulo *)
+let rem (x : int) (y : int) =
+ if y = 0 then 0 else Int64.to_int (Int64.rem (to_uint64 x) (to_uint64 y))
+
+let addmuldiv p x y =
+ l_or (l_sl x p) (l_sr y (uint_size - p))
+
+ (* comparison *)
+let lt (x : int) (y : int) =
+ (x lxor 0x4000000000000000) < (y lxor 0x4000000000000000)
+[@@ocaml.inline always]
+
+let le (x : int) (y : int) =
+ (x lxor 0x4000000000000000) <= (y lxor 0x4000000000000000)
+[@@ocaml.inline always]
+
+(* A few helper functions on 128 bits *)
+let lt128 xh xl yh yl =
+ lt xh yh || (xh = yh && lt xl yl)
+
+let le128 xh xl yh yl =
+ lt xh yh || (xh = yh && le xl yl)
+
+ (* division of two numbers by one *)
+let div21 xh xl y =
+ let maskh = ref 0 in
+ let maskl = ref 1 in
+ let dh = ref 0 in
+ let dl = ref y in
+ let cmp = ref true in
+ while !dh >= 0 && !cmp do
+ cmp := lt128 !dh !dl xh xl;
+ (* We don't use addmuldiv below to avoid checks on 1 *)
+ dh := (!dh lsl 1) lor (!dl lsr (uint_size - 1));
+ dl := !dl lsl 1;
+ maskh := (!maskh lsl 1) lor (!maskl lsr (uint_size - 1));
+ maskl := !maskl lsl 1
+ done; (* mask = 2^N, d = 2^N * d, d >= x *)
+ let remh = ref xh in
+ let reml = ref xl in
+ let quotient = ref 0 in
+ while !maskh lor !maskl <> 0 do
+ if le128 !dh !dl !remh !reml then begin (* if rem >= d, add one bit and subtract d *)
+ quotient := !quotient lor !maskl;
+ remh := if lt !reml !dl then !remh - !dh - 1 else !remh - !dh;
+ reml := !reml - !dl;
+ end;
+ maskl := (!maskl lsr 1) lor (!maskh lsl (uint_size - 1));
+ maskh := !maskh lsr 1;
+ dl := (!dl lsr 1) lor (!dh lsl (uint_size - 1));
+ dh := !dh lsr 1;
+ done;
+ !quotient, !reml
+
+ (* exact multiplication *)
+(* TODO: check that none of these additions could be a logical or *)
+
+
+(* size = 32 + 31
+ (hx << 31 + lx) * (hy << 31 + ly) =
+ hxhy << 62 + (hxly + lxhy) << 31 + lxly
+*)
+
+(* precondition : (x lsr 62 = 0 || y lsr 62 = 0) *)
+let mulc_aux x y =
+ let lx = x land maxuint31 in
+ let ly = y land maxuint31 in
+ let hx = x lsr 31 in
+ let hy = y lsr 31 in
+ (* hx and hy are 32 bits value but at most one is 32 *)
+ let hxy = hx * hy in (* 63 bits *)
+ let hxly = hx * ly in (* 63 bits *)
+ let lxhy = lx * hy in (* 63 bits *)
+ let lxy = lx * ly in (* 62 bits *)
+ let l = lxy lor (hxy lsl 62) (* 63 bits *) in
+ let h = hxy lsr 1 in (* 62 bits *)
+ let hl = hxly + lxhy in (* We can have a carry *)
+ let h = if lt hl hxly then h + (1 lsl 31) else h in
+ let hl'= hl lsl 31 in
+ let l = l + hl' in
+ let h = if lt l hl' then h + 1 else h in
+ let h = h + (hl lsr 32) in
+ (h,l)
+
+let mulc x y =
+ if (x lsr 62 = 0 || y lsr 62 = 0) then mulc_aux x y
+ else
+ let yl = y lxor (1 lsl 62) in
+ let (h,l) = mulc_aux x yl in
+ (* h << 63 + l = x * yl
+ x * y = x * (1 << 62 + yl) =
+ x << 62 + x*yl = x << 62 + h << 63 + l *)
+ let l' = l + (x lsl 62) in
+ let h = if lt l' l then h + 1 else h in
+ (h + (x lsr 1), l')
+
+let equal (x : int) (y : int) = x = y
+[@@ocaml.inline always]
+
+let compare (x:int) (y:int) =
+ let x = x lxor 0x4000000000000000 in
+ let y = y lxor 0x4000000000000000 in
+ if x > y then 1
+ else if y > x then -1
+ else 0
+
+ (* head tail *)
+
+let head0 x =
+ let r = ref 0 in
+ let x = ref x in
+ if !x land 0x7FFFFFFF00000000 = 0 then r := !r + 31
+ else x := !x lsr 31;
+ if !x land 0xFFFF0000 = 0 then (x := !x lsl 16; r := !r + 16);
+ if !x land 0xFF000000 = 0 then (x := !x lsl 8; r := !r + 8);
+ if !x land 0xF0000000 = 0 then (x := !x lsl 4; r := !r + 4);
+ if !x land 0xC0000000 = 0 then (x := !x lsl 2; r := !r + 2);
+ if !x land 0x80000000 = 0 then (x := !x lsl 1; r := !r + 1);
+ if !x land 0x80000000 = 0 then ( r := !r + 1);
+ !r;;
+
+let tail0 x =
+ let r = ref 0 in
+ let x = ref x in
+ if !x land 0xFFFFFFFF = 0 then (x := !x lsr 32; r := !r + 32);
+ if !x land 0xFFFF = 0 then (x := !x lsr 16; r := !r + 16);
+ if !x land 0xFF = 0 then (x := !x lsr 8; r := !r + 8);
+ if !x land 0xF = 0 then (x := !x lsr 4; r := !r + 4);
+ if !x land 0x3 = 0 then (x := !x lsr 2; r := !r + 2);
+ if !x land 0x1 = 0 then ( r := !r + 1);
+ !r
+
+let is_uint63 t =
+ Obj.is_int t
+[@@ocaml.inline always]
diff --git a/kernel/uint63_x86.ml b/kernel/uint63_x86.ml
new file mode 100644
index 0000000000..461184c432
--- /dev/null
+++ b/kernel/uint63_x86.ml
@@ -0,0 +1,209 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(* Invariant: the msb should be 0 *)
+type t = Int64.t
+
+let _ = assert (Sys.word_size = 32)
+
+let uint_size = 63
+
+let maxuint63 = Int64.of_string "0x7FFFFFFFFFFFFFFF"
+let maxuint31 = Int64.of_string "0x7FFFFFFF"
+
+let zero = Int64.zero
+let one = Int64.one
+
+ (* conversion from an int *)
+let mask63 i = Int64.logand i maxuint63
+let of_int i = Int64.of_int i
+let to_int2 i = (Int64.to_int (Int64.shift_right_logical i 31), Int64.to_int i)
+let of_int64 i = i
+let hash i =
+ let (h,l) = to_int2 i in
+ (*Hashset.combine h l*)
+ h * 65599 + l
+
+ (* conversion of an uint63 to a string *)
+let to_string i = Int64.to_string i
+
+let of_string s =
+ let i64 = Int64.of_string s in
+ if Int64.compare Int64.zero i64 <= 0
+ && Int64.compare i64 maxuint63 <= 0
+ then i64
+ else raise (Failure "Int63.of_string")
+
+(* Compiles an unsigned int to OCaml code *)
+let compile i = Printf.sprintf "Uint63.of_int64 (%LiL)" i
+
+ (* comparison *)
+let lt x y =
+ Int64.compare x y < 0
+
+let le x y =
+ Int64.compare x y <= 0
+
+ (* logical shift *)
+let l_sl x y =
+ if le 0L y && lt y 63L then mask63 (Int64.shift_left x (Int64.to_int y)) else 0L
+
+let l_sr x y =
+ if le 0L y && lt y 63L then Int64.shift_right x (Int64.to_int y) else 0L
+
+let l_and x y = Int64.logand x y
+let l_or x y = Int64.logor x y
+let l_xor x y = Int64.logxor x y
+
+ (* addition of int63 *)
+let add x y = mask63 (Int64.add x y)
+
+let addcarry x y = add (add x y) Int64.one
+
+ (* subtraction *)
+let sub x y = mask63 (Int64.sub x y)
+
+let subcarry x y = sub (sub x y) Int64.one
+
+ (* multiplication *)
+let mul x y = mask63 (Int64.mul x y)
+
+ (* division *)
+let div x y =
+ if y = 0L then 0L else Int64.div x y
+
+ (* modulo *)
+let rem x y =
+ if y = 0L then 0L else Int64.rem x y
+
+let addmuldiv p x y =
+ l_or (l_sl x p) (l_sr y Int64.(sub (of_int uint_size) p))
+
+(* A few helper functions on 128 bits *)
+let lt128 xh xl yh yl =
+ lt xh yh || (xh = yh && lt xl yl)
+
+let le128 xh xl yh yl =
+ lt xh yh || (xh = yh && le xl yl)
+
+ (* division of two numbers by one *)
+let div21 xh xl y =
+ let maskh = ref zero in
+ let maskl = ref one in
+ let dh = ref zero in
+ let dl = ref y in
+ let cmp = ref true in
+ while le zero !dh && !cmp do
+ cmp := lt128 !dh !dl xh xl;
+ (* We don't use addmuldiv below to avoid checks on 1 *)
+ dh := l_or (l_sl !dh one) (l_sr !dl (of_int (uint_size - 1)));
+ dl := l_sl !dl one;
+ maskh := l_or (l_sl !maskh one) (l_sr !maskl (of_int (uint_size - 1)));
+ maskl := l_sl !maskl one
+ done; (* mask = 2^N, d = 2^N * d, d >= x *)
+ let remh = ref xh in
+ let reml = ref xl in
+ let quotient = ref zero in
+ while not (Int64.equal (l_or !maskh !maskl) zero) do
+ if le128 !dh !dl !remh !reml then begin (* if rem >= d, add one bit and subtract d *)
+ quotient := l_or !quotient !maskl;
+ remh := if lt !reml !dl then sub (sub !remh !dh) one else sub !remh !dh;
+ reml := sub !reml !dl
+ end;
+ maskl := l_or (l_sr !maskl one) (l_sl !maskh (of_int (uint_size - 1)));
+ maskh := l_sr !maskh one;
+ dl := l_or (l_sr !dl one) (l_sl !dh (of_int (uint_size - 1)));
+ dh := l_sr !dh one
+ done;
+ !quotient, !reml
+
+
+ (* exact multiplication *)
+let mulc x y =
+ let lx = ref (Int64.logand x maxuint31) in
+ let ly = ref (Int64.logand y maxuint31) in
+ let hx = Int64.shift_right x 31 in
+ let hy = Int64.shift_right y 31 in
+ let hr = ref (Int64.mul hx hy) in
+ let lr = ref (Int64.logor (Int64.mul !lx !ly) (Int64.shift_left !hr 62)) in
+ hr := (Int64.shift_right_logical !hr 1);
+ lx := Int64.mul !lx hy;
+ ly := Int64.mul hx !ly;
+ hr := Int64.logor !hr (Int64.add (Int64.shift_right !lx 32) (Int64.shift_right !ly 32));
+ lr := Int64.add !lr (Int64.shift_left !lx 31);
+ hr := Int64.add !hr (Int64.shift_right_logical !lr 63);
+ lr := Int64.add (Int64.shift_left !ly 31) (mask63 !lr);
+ hr := Int64.add !hr (Int64.shift_right_logical !lr 63);
+ if Int64.logand !lr Int64.min_int <> 0L
+ then Int64.(sub !hr one, mask63 !lr)
+ else (!hr, !lr)
+
+let equal x y = mask63 x = mask63 y
+
+let compare x y = Int64.compare x y
+
+(* Number of leading zeroes *)
+let head0 x =
+ let r = ref 0 in
+ let x = ref x in
+ if Int64.logand !x 0x7FFFFFFF00000000L = 0L then r := !r + 31
+ else x := Int64.shift_right !x 31;
+ if Int64.logand !x 0xFFFF0000L = 0L then (x := Int64.shift_left !x 16; r := !r + 16);
+ if Int64.logand !x 0xFF000000L = 0L then (x := Int64.shift_left !x 8; r := !r + 8);
+ if Int64.logand !x 0xF0000000L = 0L then (x := Int64.shift_left !x 4; r := !r + 4);
+ if Int64.logand !x 0xC0000000L = 0L then (x := Int64.shift_left !x 2; r := !r + 2);
+ if Int64.logand !x 0x80000000L = 0L then (x := Int64.shift_left !x 1; r := !r + 1);
+ if Int64.logand !x 0x80000000L = 0L then (r := !r + 1);
+ Int64.of_int !r
+
+(* Number of trailing zeroes *)
+let tail0 x =
+ let r = ref 0 in
+ let x = ref x in
+ if Int64.logand !x 0xFFFFFFFFL = 0L then (x := Int64.shift_right !x 32; r := !r + 32);
+ if Int64.logand !x 0xFFFFL = 0L then (x := Int64.shift_right !x 16; r := !r + 16);
+ if Int64.logand !x 0xFFL = 0L then (x := Int64.shift_right !x 8; r := !r + 8);
+ if Int64.logand !x 0xFL = 0L then (x := Int64.shift_right !x 4; r := !r + 4);
+ if Int64.logand !x 0x3L = 0L then (x := Int64.shift_right !x 2; r := !r + 2);
+ if Int64.logand !x 0x1L = 0L then (r := !r + 1);
+ Int64.of_int !r
+
+(* May an object be safely cast into an Uint63.t ? *)
+let is_uint63 t =
+ Obj.is_block t && Int.equal (Obj.tag t) Obj.custom_tag
+ && le (Obj.magic t) maxuint63
+
+(* Register all exported functions so that they can be called from C code *)
+
+let () =
+ Callback.register "uint63 add" add;
+ Callback.register "uint63 addcarry" addcarry;
+ Callback.register "uint63 addmuldiv" addmuldiv;
+ Callback.register "uint63 div" div;
+ Callback.register "uint63 div21_ml" div21;
+ Callback.register "uint63 eq" equal;
+ Callback.register "uint63 eq0" (equal Int64.zero);
+ Callback.register "uint63 head0" head0;
+ Callback.register "uint63 land" l_and;
+ Callback.register "uint63 leq" le;
+ Callback.register "uint63 lor" l_or;
+ Callback.register "uint63 lsl" l_sl;
+ Callback.register "uint63 lsl1" (fun x -> l_sl x Int64.one);
+ Callback.register "uint63 lsr" l_sr;
+ Callback.register "uint63 lsr1" (fun x -> l_sr x Int64.one);
+ Callback.register "uint63 lt" lt;
+ Callback.register "uint63 lxor" l_xor;
+ Callback.register "uint63 mod" rem;
+ Callback.register "uint63 mul" mul;
+ Callback.register "uint63 mulc_ml" mulc;
+ Callback.register "uint63 one" one;
+ Callback.register "uint63 sub" sub;
+ Callback.register "uint63 subcarry" subcarry;
+ Callback.register "uint63 tail0" tail0
diff --git a/kernel/vconv.ml b/kernel/vconv.ml
index 246c90c09d..414c443c4e 100644
--- a/kernel/vconv.ml
+++ b/kernel/vconv.ml
@@ -71,13 +71,15 @@ and conv_whd env pb k whd1 whd2 cu =
done;
!rcu
else raise NotConvertible
+ | Vint64 i1, Vint64 i2 ->
+ if Int64.equal i1 i2 then cu else raise NotConvertible
| Vatom_stk(a1,stk1), Vatom_stk(a2,stk2) ->
conv_atom env pb k a1 stk1 a2 stk2 cu
| Vfun _, _ | _, Vfun _ ->
(* on the fly eta expansion *)
conv_val env CONV (k+1) (apply_whd k whd1) (apply_whd k whd2) cu
- | Vprod _, _ | Vfix _, _ | Vcofix _, _ | Vconstr_const _, _
+ | Vprod _, _ | Vfix _, _ | Vcofix _, _ | Vconstr_const _, _ | Vint64 _, _
| Vconstr_block _, _ | Vatom_stk _, _ -> raise NotConvertible
@@ -86,17 +88,11 @@ and conv_atom env pb k a1 stk1 a2 stk2 cu =
match a1, a2 with
| Aind ((mi,_i) as ind1) , Aind ind2 ->
if eq_ind ind1 ind2 && compare_stack stk1 stk2 then
- if Environ.polymorphic_ind ind1 env then
- let mib = Environ.lookup_mind mi env in
- let ulen =
- match mib.Declarations.mind_universes with
- | Declarations.Monomorphic_ind ctx -> Univ.ContextSet.size ctx
- | Declarations.Polymorphic_ind auctx -> Univ.AUContext.size auctx
- | Declarations.Cumulative_ind cumi ->
- Univ.AUContext.size (Univ.ACumulativityInfo.univ_context cumi)
- in
+ let ulen = Univ.AUContext.size (Environ.mind_context env mi) in
+ if ulen = 0 then
+ conv_stack env k stk1 stk2 cu
+ else
match stk1 , stk2 with
- | [], [] -> assert (Int.equal ulen 0); cu
| Zapp args1 :: stk1' , Zapp args2 :: stk2' ->
assert (ulen <= nargs args1);
assert (ulen <= nargs args2);
@@ -108,8 +104,6 @@ and conv_atom env pb k a1 stk1 a2 stk2 cu =
conv_arguments env ~from:ulen k args1 args2
(conv_stack env k stk1' stk2' cu)
| _, _ -> assert false (* Should not happen if problem is well typed *)
- else
- conv_stack env k stk1 stk2 cu
else raise NotConvertible
| Aid ik1, Aid ik2 ->
if Vmvalues.eq_id_key ik1 ik2 && compare_stack stk1 stk2 then
diff --git a/kernel/vm.ml b/kernel/vm.ml
index eaf64ba4af..83312a8530 100644
--- a/kernel/vm.ml
+++ b/kernel/vm.ml
@@ -7,7 +7,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-
open Vmvalues
external set_drawinstr : unit -> unit = "coq_set_drawinstr"
@@ -170,7 +169,7 @@ let rec apply_stack a stk v =
let apply_whd k whd =
let v = val_of_rel k in
match whd with
- | Vprod _ | Vconstr_const _ | Vconstr_block _ -> assert false
+ | Vprod _ | Vconstr_const _ | Vconstr_block _ | Vint64 _ -> assert false
| Vfun f -> reduce_fun k f
| Vfix(f, None) ->
push_ra stop;
diff --git a/kernel/vmvalues.ml b/kernel/vmvalues.ml
index 217ef4b8e5..9a3eadf747 100644
--- a/kernel/vmvalues.ml
+++ b/kernel/vmvalues.ml
@@ -57,6 +57,7 @@ type structured_constant =
| Const_b0 of tag
| Const_univ_level of Univ.Level.t
| Const_val of structured_values
+ | Const_uint of Uint63.t
type reloc_table = (tag * int) array
@@ -73,7 +74,9 @@ let rec eq_structured_values v1 v2 =
let t2 = Obj.tag o2 in
if Int.equal t1 t2 &&
Int.equal (Obj.size o1) (Obj.size o2)
- then begin
+ then if Int.equal t1 Obj.custom_tag
+ then Int64.equal (Obj.magic v1 : int64) (Obj.magic v2 : int64)
+ else begin
assert (t1 <= Obj.last_non_constant_constructor_tag &&
t2 <= Obj.last_non_constant_constructor_tag);
let i = ref 0 in
@@ -100,7 +103,9 @@ let eq_structured_constant c1 c2 = match c1, c2 with
| Const_univ_level l1 , Const_univ_level l2 -> Univ.Level.equal l1 l2
| Const_univ_level _ , _ -> false
| Const_val v1, Const_val v2 -> eq_structured_values v1 v2
-| Const_val _v1, _ -> false
+| Const_val _, _ -> false
+| Const_uint i1, Const_uint i2 -> Uint63.equal i1 i2
+| Const_uint _, _ -> false
let hash_structured_constant c =
let open Hashset.Combine in
@@ -110,6 +115,7 @@ let hash_structured_constant c =
| Const_b0 t -> combinesmall 3 (Int.hash t)
| Const_univ_level l -> combinesmall 4 (Univ.Level.hash l)
| Const_val v -> combinesmall 5 (hash_structured_values v)
+ | Const_uint i -> combinesmall 6 (Uint63.hash i)
let eq_annot_switch asw1 asw2 =
let eq_ci ci1 ci2 =
@@ -142,6 +148,7 @@ let pp_struct_const = function
| Const_b0 i -> Pp.int i
| Const_univ_level l -> Univ.Level.pr l
| Const_val _ -> Pp.str "(value)"
+ | Const_uint i -> Pp.str (Uint63.to_string i)
(* Abstract data *)
type vprod
@@ -276,6 +283,7 @@ type whd =
| Vcofix of vcofix * to_update * arguments option
| Vconstr_const of int
| Vconstr_block of vblock
+ | Vint64 of int64
| Vatom_stk of atom * stack
| Vuniv_level of Univ.Level.t
@@ -306,8 +314,9 @@ let uni_lvl_val (v : values) : Univ.Level.t =
| Vcofix _ -> str "Vcofix"
| Vconstr_const _i -> str "Vconstr_const"
| Vconstr_block _b -> str "Vconstr_block"
+ | Vint64 _ -> str "Vint64"
| Vatom_stk (_a,_stk) -> str "Vatom_stk"
- | _ -> assert false
+ | Vuniv_level _ -> assert false
in
CErrors.anomaly
Pp.( strbrk "Parsing virtual machine value expected universe level, got "
@@ -363,6 +372,8 @@ let rec whd_accu a stk =
| [Zapp args] -> Vcofix(vcofix, res, Some args)
| _ -> assert false
end
+ | i when Int.equal i Obj.custom_tag ->
+ Vint64 (Obj.magic i)
| tg ->
CErrors.anomaly
Pp.(strbrk "Failed to parse VM value. Tag = " ++ int tg ++ str ".")
@@ -391,6 +402,7 @@ let whd_val : values -> whd =
| 2 -> Vfix(Obj.obj (Obj.field o 1), Some (Obj.obj o))
| 3 -> Vatom_stk(Aid(RelKey(int_tcode (fun_code o) 1)), [])
| _ -> CErrors.anomaly ~label:"Vm.whd " (Pp.str "kind_of_closure does not work."))
+ else if Int.equal tag Obj.custom_tag then Vint64 (Obj.magic v)
else
Vconstr_block(Obj.obj o)
@@ -413,6 +425,7 @@ let obj_of_str_const str =
| Const_b0 tag -> Obj.repr tag
| Const_univ_level l -> Obj.repr (Vuniv_level l)
| Const_val v -> Obj.repr v
+ | Const_uint i -> Obj.repr i
let val_of_block tag (args : structured_values array) =
let nargs = Array.length args in
@@ -430,6 +443,8 @@ let val_of_atom a = val_of_obj (obj_of_atom a)
let val_of_int i = (Obj.magic i : values)
+let val_of_uint i = (Obj.magic i : values)
+
let atom_of_proj kn v =
let r = Obj.new_block proj_tag 2 in
Obj.set_field r 0 (Obj.repr kn);
@@ -659,6 +674,7 @@ and pr_whd w =
| Vcofix _ -> str "Vcofix"
| Vconstr_const i -> str "Vconstr_const(" ++ int i ++ str ")"
| Vconstr_block _b -> str "Vconstr_block"
+ | Vint64 i -> i |> Format.sprintf "Vint64(%LiL)" |> str
| Vatom_stk (a,stk) -> str "Vatom_stk(" ++ pr_atom a ++ str ", " ++ pr_stack stk ++ str ")"
| Vuniv_level _ -> assert false)
and pr_stack stk =
diff --git a/kernel/vmvalues.mli b/kernel/vmvalues.mli
index ae1d416ed5..6d984d5f49 100644
--- a/kernel/vmvalues.mli
+++ b/kernel/vmvalues.mli
@@ -44,6 +44,7 @@ type structured_constant =
| Const_b0 of tag
| Const_univ_level of Univ.Level.t
| Const_val of structured_values
+ | Const_uint of Uint63.t
val pp_struct_const : structured_constant -> Pp.t
@@ -125,6 +126,7 @@ type whd =
| Vcofix of vcofix * to_update * arguments option
| Vconstr_const of int
| Vconstr_block of vblock
+ | Vint64 of int64
| Vatom_stk of atom * stack
| Vuniv_level of Univ.Level.t
@@ -145,6 +147,7 @@ val val_of_proj : Projection.Repr.t -> values -> values
val val_of_atom : atom -> values
val val_of_int : int -> structured_values
val val_of_block : tag -> structured_values array -> structured_values
+val val_of_uint : Uint63.t -> structured_values
external val_of_annot_switch : annot_switch -> values = "%identity"
external val_of_proj_name : Projection.Repr.t -> values = "%identity"
diff --git a/kernel/write_uint63.ml b/kernel/write_uint63.ml
new file mode 100644
index 0000000000..0fcaf4f10a
--- /dev/null
+++ b/kernel/write_uint63.ml
@@ -0,0 +1,30 @@
+(** Equivalent of rm -f *)
+
+let safe_remove f =
+ try Unix.chmod f 0o644; Sys.remove f with _ -> ()
+
+(** * Generate an implementation of 63-bit arithmetic *)
+
+let ml_file_copy input output =
+ safe_remove output;
+ let i = open_in input in
+ let o = open_out output in
+ let pr s = Printf.fprintf o s in
+ pr "(* DO NOT EDIT THIS FILE: automatically generated by ./write_uint63.ml *)\n";
+ pr "(* see uint63_amd64.ml and uint63_x86.ml *)\n";
+ try
+ while true do
+ output_string o (input_line i); output_char o '\n'
+ done
+ with End_of_file ->
+ close_in i;
+ close_out o;
+ Unix.chmod output 0o444
+
+let write_uint63 () =
+ ml_file_copy
+ (if max_int = 1073741823 (* 32-bits *) then "uint63_x86.ml"
+ else (* 64 bits *) "uint63_amd64.ml")
+ "uint63.ml"
+
+let () = write_uint63 ()
diff --git a/lib/flags.ml b/lib/flags.ml
index ae4d337ded..55bfa3cbde 100644
--- a/lib/flags.ml
+++ b/lib/flags.ml
@@ -66,7 +66,7 @@ let we_are_parsing = ref false
(* Current means no particular compatibility consideration.
For correct comparisons, this constructor should remain the last one. *)
-type compat_version = V8_7 | V8_8 | Current
+type compat_version = V8_7 | V8_8 | V8_9 | Current
let compat_version = ref Current
@@ -77,6 +77,9 @@ let version_compare v1 v2 = match v1, v2 with
| V8_8, V8_8 -> 0
| V8_8, _ -> -1
| _, V8_8 -> 1
+ | V8_9, V8_9 -> 0
+ | V8_9, _ -> -1
+ | _, V8_9 -> 1
| Current, Current -> 0
let version_strictly_greater v = version_compare !compat_version v > 0
@@ -85,6 +88,7 @@ let version_less_or_equal v = not (version_strictly_greater v)
let pr_version = function
| V8_7 -> "8.7"
| V8_8 -> "8.8"
+ | V8_9 -> "8.9"
| Current -> "current"
(* Translate *)
diff --git a/lib/flags.mli b/lib/flags.mli
index d883cf1e30..7336b9beaf 100644
--- a/lib/flags.mli
+++ b/lib/flags.mli
@@ -58,7 +58,7 @@ val we_are_parsing : bool ref
(* Set Printing All flag. For some reason it is a global flag *)
val raw_print : bool ref
-type compat_version = V8_7 | V8_8 | Current
+type compat_version = V8_7 | V8_8 | V8_9 | Current
val compat_version : compat_version ref
val version_compare : compat_version -> compat_version -> int
val version_strictly_greater : compat_version -> bool
diff --git a/lib/stateid.ml b/lib/stateid.ml
index 5485c4bf19..8f45f3605d 100644
--- a/lib/stateid.ml
+++ b/lib/stateid.ml
@@ -27,6 +27,8 @@ let get exn = Exninfo.get exn state_id_info
let equal = Int.equal
let compare = Int.compare
+let print id = Pp.int id
+
module Self = struct
type t = int
let compare = compare
diff --git a/lib/stateid.mli b/lib/stateid.mli
index 5d4b71a354..f6ce7ddc40 100644
--- a/lib/stateid.mli
+++ b/lib/stateid.mli
@@ -20,6 +20,7 @@ val initial : t
val dummy : t
val fresh : unit -> t
val to_string : t -> string
+val print : t -> Pp.t
val of_int : int -> t
val to_int : t -> int
diff --git a/library/decl_kinds.ml b/library/decl_kinds.ml
index 171d51800e..8d5c2fb687 100644
--- a/library/decl_kinds.ml
+++ b/library/decl_kinds.ml
@@ -70,6 +70,7 @@ type goal_kind = locality * polymorphic * goal_object_kind
(** Kinds used in library *)
type logical_kind =
+ | IsPrimitive
| IsAssumption of assumption_object_kind
| IsDefinition of definition_object_kind
| IsProof of theorem_kind
diff --git a/library/global.ml b/library/global.ml
index 84d2a37170..784a02449c 100644
--- a/library/global.ml
+++ b/library/global.ml
@@ -175,11 +175,8 @@ let with_global f =
let (a, ctx) = f (env ()) (current_dirpath ()) in
push_context_set false ctx; a
-(* spiwack: register/unregister functions for retroknowledge *)
-let register field value =
- globalize0 (Safe_typing.register field value)
-
let register_inline c = globalize0 (Safe_typing.register_inline c)
+let register_inductive c r = globalize0 (Safe_typing.register_inductive c r)
let set_strategy k l =
globalize0 (Safe_typing.set_strategy k l)
diff --git a/library/global.mli b/library/global.mli
index 40962e21af..df18625a5f 100644
--- a/library/global.mli
+++ b/library/global.mli
@@ -142,10 +142,8 @@ val universes_of_global : GlobRef.t -> Univ.AUContext.t
(** {6 Retroknowledge } *)
-val register :
- Retroknowledge.field -> GlobRef.t -> unit
-
val register_inline : Constant.t -> unit
+val register_inductive : inductive -> CPrimitives.prim_ind -> unit
(** {6 Oracle } *)
diff --git a/library/keys.ml b/library/keys.ml
index 58883ccc88..45b6fae2f0 100644
--- a/library/keys.ml
+++ b/library/keys.ml
@@ -25,13 +25,14 @@ type key =
| KFix
| KCoFix
| KRel
+ | KInt
module KeyOrdered = struct
type t = key
let hash gr =
match gr with
- | KGlob gr -> 8 + GlobRef.Ordered.hash gr
+ | KGlob gr -> 9 + GlobRef.Ordered.hash gr
| KLam -> 0
| KLet -> 1
| KProd -> 2
@@ -40,6 +41,7 @@ module KeyOrdered = struct
| KFix -> 5
| KCoFix -> 6
| KRel -> 7
+ | KInt -> 8
let compare gr1 gr2 =
match gr1, gr2 with
@@ -133,6 +135,7 @@ let constr_key kind c =
| Evar _ -> raise Not_found
| Sort _ -> KSort
| LetIn _ -> KLet
+ | Int _ -> KInt
in Some (aux c)
with Not_found -> None
@@ -148,6 +151,7 @@ let pr_key pr_global = function
| KFix -> str"Fix"
| KCoFix -> str"CoFix"
| KRel -> str"Rel"
+ | KInt -> str"Int"
let pr_keyset pr_global v =
prlist_with_sep spc (pr_key pr_global) (Keyset.elements v)
diff --git a/man/coqtop.1 b/man/coqtop.1
index 084adfe453..addfb54672 100644
--- a/man/coqtop.1
+++ b/man/coqtop.1
@@ -85,22 +85,6 @@ load Coq library
and import it (Require Import path.)
.TP
-.BI \-compile \ filename.v
-compile Coq file
-.I filename.v
-(implies
-.B \-batch
-)
-
-.TP
-.BI \-compile\-verbose \ filename.v
-verbosely compile Coq file
-.I filename.v
-(implies
-.B \-batch
-)
-
-.TP
.B \-where
print Coq's standard library location and exit
@@ -125,8 +109,6 @@ batch mode (exits just after arguments parsing)
.B \-boot
boot mode (implies
.B \-q
-and
-.B \-batch
)
.TP
diff --git a/parsing/pcoq.ml b/parsing/pcoq.ml
index 19ae97da77..759e60fbca 100644
--- a/parsing/pcoq.ml
+++ b/parsing/pcoq.ml
@@ -439,7 +439,6 @@ module Module =
let module_expr = Entry.create "module_expr"
let module_type = Entry.create "module_type"
end
-
let epsilon_value f e =
let r = G.production (G.r_next G.r_stop (symbol_of_prod_entry_key e), (fun x _ -> f x)) in
let ext = [None, None, [r]] in
diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli
index 352857d4cd..3203a25b46 100644
--- a/parsing/pcoq.mli
+++ b/parsing/pcoq.mli
@@ -41,6 +41,16 @@ end
- static rules explicitly defined in files g_*.ml4
- static rules macro-generated by ARGUMENT EXTEND, TACTIC EXTEND and
VERNAC EXTEND (see e.g. file extratactics.ml4)
+
+ Note that parsing a Coq document is in essence stateful: the parser
+ needs to recognize commands that start proofs and use a different
+ parsing entry point for them.
+
+ We thus provide two different interfaces: the "raw" parsing
+ interface, in the style of camlp5, which provides more flexibility,
+ and a more specialize "parse_vernac" one, which will indeed adjust
+ the state as needed.
+
*)
(** Dynamic extension of rules
@@ -269,3 +279,7 @@ type any_entry = AnyEntry : 'a Entry.t -> any_entry
val register_grammars_by_name : string -> any_entry list -> unit
val find_grammars_by_name : string -> any_entry list
+
+(** Parsing state handling *)
+val freeze : marshallable:bool -> frozen_t
+val unfreeze : frozen_t -> unit
diff --git a/plugins/derive/g_derive.mlg b/plugins/derive/g_derive.mlg
index df4b647642..0cdf8fb5d8 100644
--- a/plugins/derive/g_derive.mlg
+++ b/plugins/derive/g_derive.mlg
@@ -18,7 +18,7 @@ DECLARE PLUGIN "derive_plugin"
{
-let classify_derive_command _ = Vernacextend.(VtStartProof ("Classic",Doesn'tGuaranteeOpacity,[]),VtLater)
+let classify_derive_command _ = Vernacextend.(VtStartProof (Doesn'tGuaranteeOpacity,[]),VtLater)
}
diff --git a/plugins/extraction/extract_env.ml b/plugins/extraction/extract_env.ml
index b0f6301192..b59e3b608c 100644
--- a/plugins/extraction/extract_env.ml
+++ b/plugins/extraction/extract_env.ml
@@ -147,7 +147,7 @@ let check_fix env sg cb i =
| Fix ((_,j),recd) when Int.equal i j -> check_arity env cb; (true,recd)
| CoFix (j,recd) when Int.equal i j -> check_arity env cb; (false,recd)
| _ -> raise Impossible)
- | Undef _ | OpaqueDef _ -> raise Impossible
+ | Undef _ | OpaqueDef _ | Primitive _ -> raise Impossible
let prec_declaration_equal sg (na1, ca1, ta1) (na2, ca2, ta2) =
Array.equal Name.equal na1 na2 &&
diff --git a/plugins/extraction/extraction.ml b/plugins/extraction/extraction.ml
index 67c605ea1d..c15486ea10 100644
--- a/plugins/extraction/extraction.ml
+++ b/plugins/extraction/extraction.ml
@@ -304,9 +304,9 @@ let rec extract_type env sg db j c args =
| (Info, TypeScheme) ->
let mlt = extract_type_app env sg db (r, type_sign env sg typ) args in
(match (lookup_constant kn env).const_body with
- | Undef _ | OpaqueDef _ -> mlt
- | Def _ when is_custom (ConstRef kn) -> mlt
- | Def lbody ->
+ | Undef _ | OpaqueDef _ | Primitive _ -> mlt
+ | Def _ when is_custom (ConstRef kn) -> mlt
+ | Def lbody ->
let newc = applistc (get_body lbody) args in
let mlt' = extract_type env sg db j newc [] in
(* ML type abbreviations interact badly with Coq *)
@@ -318,7 +318,7 @@ let rec extract_type env sg db j c args =
| (Info, Default) ->
(* Not an ML type, for example [(c:forall X, X->X) Type nat] *)
(match (lookup_constant kn env).const_body with
- | Undef _ | OpaqueDef _ -> Tunknown (* Brutal approx ... *)
+ | Undef _ | OpaqueDef _ | Primitive _ -> Tunknown (* Brutal approx ... *)
| Def lbody ->
(* We try to reduce. *)
let newc = applistc (get_body lbody) args in
@@ -346,7 +346,7 @@ let rec extract_type env sg db j c args =
| (Info, TypeScheme) ->
extract_type_app env sg db (r, type_sign env sg ty) args
| (Info, Default) -> Tunknown))
- | Cast _ | LetIn _ | Construct _ -> assert false
+ | Cast _ | LetIn _ | Construct _ | Int _ -> assert false
(*s Auxiliary function dealing with type application.
Precondition: [r] is a type scheme represented by the signature [s],
@@ -564,7 +564,7 @@ and mlt_env env r = match r with
| ConstRef kn ->
let cb = Environ.lookup_constant kn env in
match cb.const_body with
- | Undef _ | OpaqueDef _ -> None
+ | Undef _ | OpaqueDef _ | Primitive _ -> None
| Def l_body ->
match lookup_typedef kn cb with
| Some _ as o -> o
@@ -683,6 +683,7 @@ let rec extract_term env sg mle mlt c args =
let vty = extract_type env sg [] 0 ty [] in
let extract_var mlt = put_magic (mlt,vty) (MLglob (VarRef v)) in
extract_app env sg mle mlt extract_var args
+ | Int i -> assert (args = []); MLuint i
| Ind _ | Prod _ | Sort _ -> assert false
(*s [extract_maybe_term] is [extract_term] for usual terms, else [MLdummy] *)
@@ -1063,7 +1064,7 @@ let extract_constant env kn cb =
| (Logic,Default) -> warn_log (); Dterm (r, MLdummy Kprop, Tdummy Kprop)
| (Info,TypeScheme) ->
(match cb.const_body with
- | Undef _ -> warn_info (); mk_typ_ax ()
+ | Primitive _ | Undef _ -> warn_info (); mk_typ_ax ()
| Def c ->
(match Recordops.find_primitive_projection kn with
| None -> mk_typ (get_body c)
@@ -1079,7 +1080,7 @@ let extract_constant env kn cb =
else mk_typ_ax ())
| (Info,Default) ->
(match cb.const_body with
- | Undef _ -> warn_info (); mk_ax ()
+ | Primitive _ | Undef _ -> warn_info (); mk_ax ()
| Def c ->
(match Recordops.find_primitive_projection kn with
| None -> mk_def (get_body c)
@@ -1107,7 +1108,7 @@ let extract_constant_spec env kn cb =
| (Info, TypeScheme) ->
let s,vl = type_sign_vl env sg typ in
(match cb.const_body with
- | Undef _ | OpaqueDef _ -> Stype (r, vl, None)
+ | Undef _ | OpaqueDef _ | Primitive _ -> Stype (r, vl, None)
| Def body ->
let db = db_from_sign s in
let body = get_body body in
diff --git a/plugins/extraction/haskell.ml b/plugins/extraction/haskell.ml
index 97fe9f24d5..a3cd92d556 100644
--- a/plugins/extraction/haskell.ml
+++ b/plugins/extraction/haskell.ml
@@ -214,6 +214,8 @@ let rec pp_expr par env args =
| MLmagic a ->
pp_apply (str "unsafeCoerce") par (pp_expr true env [] a :: args)
| MLaxiom -> pp_par par (str "Prelude.error \"AXIOM TO BE REALIZED\"")
+ | MLuint _ ->
+ pp_par par (str "Prelude.error \"EXTRACTION OF UINT NOT IMPLEMENTED\"")
and pp_cons_pat par r ppl =
pp_par par
diff --git a/plugins/extraction/json.ml b/plugins/extraction/json.ml
index e43c47d050..f88d29e9ed 100644
--- a/plugins/extraction/json.ml
+++ b/plugins/extraction/json.ml
@@ -155,6 +155,10 @@ let rec json_expr env = function
("value", json_expr env a)
]
| MLaxiom -> json_dict [("what", json_str "expr:axiom")]
+ | MLuint i -> json_dict [
+ ("what", json_str "expr:int");
+ ("int", json_str (Uint63.to_string i))
+ ]
and json_one_pat env (ids,p,t) =
let ids', env' = push_vars (List.rev_map id_of_mlid ids) env in json_dict [
diff --git a/plugins/extraction/miniml.ml b/plugins/extraction/miniml.ml
index ce920ad6a0..b7f80d543b 100644
--- a/plugins/extraction/miniml.ml
+++ b/plugins/extraction/miniml.ml
@@ -126,6 +126,7 @@ and ml_ast =
| MLdummy of kill_reason
| MLaxiom
| MLmagic of ml_ast
+ | MLuint of Uint63.t
and ml_pattern =
| Pcons of GlobRef.t * ml_pattern list
diff --git a/plugins/extraction/miniml.mli b/plugins/extraction/miniml.mli
index ce920ad6a0..9df0f4964e 100644
--- a/plugins/extraction/miniml.mli
+++ b/plugins/extraction/miniml.mli
@@ -126,6 +126,7 @@ and ml_ast =
| MLdummy of kill_reason
| MLaxiom
| MLmagic of ml_ast
+ | MLuint of Uint63.t
and ml_pattern =
| Pcons of GlobRef.t * ml_pattern list
diff --git a/plugins/extraction/mlutil.ml b/plugins/extraction/mlutil.ml
index 9f5c1f1a17..2432887673 100644
--- a/plugins/extraction/mlutil.ml
+++ b/plugins/extraction/mlutil.ml
@@ -66,7 +66,8 @@ let rec eq_ml_type t1 t2 = match t1, t2 with
| Tdummy k1, Tdummy k2 -> k1 == k2
| Tunknown, Tunknown -> true
| Taxiom, Taxiom -> true
-| _ -> false
+| (Tarr _ | Tglob _ | Tvar _ | Tvar' _ | Tmeta _ | Tdummy _ | Tunknown | Taxiom), _
+ -> false
and eq_ml_meta m1 m2 =
Int.equal m1.id m2.id && Option.equal eq_ml_type m1.contents m2.contents
@@ -107,7 +108,7 @@ let rec type_occurs alpha t =
| Tmeta {contents=Some u} -> type_occurs alpha u
| Tarr (t1, t2) -> type_occurs alpha t1 || type_occurs alpha t2
| Tglob (r,l) -> List.exists (type_occurs alpha) l
- | _ -> false
+ | (Tdummy _ | Tvar _ | Tvar' _ | Taxiom | Tunknown) -> false
(*s Most General Unificator *)
@@ -310,7 +311,7 @@ let isMLdummy = function MLdummy _ -> true | _ -> false
let sign_of_id = function
| Dummy -> Kill Kprop
- | _ -> Keep
+ | (Id _ | Tmp _) -> Keep
(* Classification of signatures *)
@@ -370,7 +371,10 @@ let eq_ml_ident i1 i2 = match i1, i2 with
| Dummy, Dummy -> true
| Id id1, Id id2 -> Id.equal id1 id2
| Tmp id1, Tmp id2 -> Id.equal id1 id2
-| _ -> false
+| Dummy, (Id _ | Tmp _)
+| Id _, (Dummy | Tmp _)
+| Tmp _, (Dummy | Id _)
+ -> false
let rec eq_ml_ast t1 t2 = match t1, t2 with
| MLrel i1, MLrel i2 ->
@@ -394,7 +398,8 @@ let rec eq_ml_ast t1 t2 = match t1, t2 with
| MLdummy k1, MLdummy k2 -> k1 == k2
| MLaxiom, MLaxiom -> true
| MLmagic t1, MLmagic t2 -> eq_ml_ast t1 t2
-| _ -> false
+| MLuint i1, MLuint i2 -> Uint63.equal i1 i2
+| _, _ -> false
and eq_ml_pattern p1 p2 = match p1, p2 with
| Pcons (gr1, p1), Pcons (gr2, p2) ->
@@ -426,7 +431,7 @@ let ast_iter_rel f =
| MLapp (a,l) -> iter n a; List.iter (iter n) l
| MLcons (_,_,l) | MLtuple l -> List.iter (iter n) l
| MLmagic a -> iter n a
- | MLglob _ | MLexn _ | MLdummy _ | MLaxiom -> ()
+ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ -> ()
in iter 0
(*s Map over asts. *)
@@ -445,7 +450,7 @@ let ast_map f = function
| MLcons (typ,c,l) -> MLcons (typ,c, List.map f l)
| MLtuple l -> MLtuple (List.map f l)
| MLmagic a -> MLmagic (f a)
- | MLrel _ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom as a -> a
+ | MLrel _ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ as a -> a
(*s Map over asts, with binding depth as parameter. *)
@@ -463,7 +468,7 @@ let ast_map_lift f n = function
| MLcons (typ,c,l) -> MLcons (typ,c, List.map (f n) l)
| MLtuple l -> MLtuple (List.map (f n) l)
| MLmagic a -> MLmagic (f n a)
- | MLrel _ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom as a -> a
+ | MLrel _ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ as a -> a
(*s Iter over asts. *)
@@ -477,7 +482,7 @@ let ast_iter f = function
| MLapp (a,l) -> f a; List.iter f l
| MLcons (_,_,l) | MLtuple l -> List.iter f l
| MLmagic a -> f a
- | MLrel _ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom -> ()
+ | MLrel _ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ -> ()
(*S Operations concerning De Bruijn indices. *)
@@ -513,7 +518,7 @@ let nb_occur_match =
| MLapp (a,l) -> List.fold_left (fun r a -> r+(nb k a)) (nb k a) l
| MLcons (_,_,l) | MLtuple l -> List.fold_left (fun r a -> r+(nb k a)) 0 l
| MLmagic a -> nb k a
- | MLglob _ | MLexn _ | MLdummy _ | MLaxiom -> 0
+ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ -> 0
in nb 1
(* Replace unused variables by _ *)
@@ -565,7 +570,7 @@ let dump_unused_vars a =
let b' = ren env b in
if b' == b then a else MLmagic b'
- | MLglob _ | MLexn _ | MLdummy _ | MLaxiom -> a
+ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ -> a
and ren_branch env ((ids,p,b) as tr) =
let occs = List.map (fun _ -> ref false) ids in
@@ -1398,7 +1403,7 @@ let rec ml_size = function
| MLfix(_,_,f) -> ml_size_array f
| MLletin (_,_,t) -> ml_size t
| MLmagic t -> ml_size t
- | MLglob _ | MLrel _ | MLexn _ | MLdummy _ | MLaxiom -> 0
+ | MLglob _ | MLrel _ | MLexn _ | MLdummy _ | MLaxiom | MLuint _ -> 0
and ml_size_list l = List.fold_left (fun a t -> a + ml_size t) 0 l
diff --git a/plugins/extraction/modutil.ml b/plugins/extraction/modutil.ml
index b398bc07a0..654695c232 100644
--- a/plugins/extraction/modutil.ml
+++ b/plugins/extraction/modutil.ml
@@ -108,7 +108,7 @@ let ast_iter_references do_term do_cons do_type a =
Array.iter (fun (_,p,_) -> patt_iter_references do_cons p) v
| MLrel _ | MLlam _ | MLapp _ | MLletin _ | MLtuple _ | MLfix _ | MLexn _
- | MLdummy _ | MLaxiom | MLmagic _ -> ()
+ | MLdummy _ | MLaxiom | MLmagic _ | MLuint _ -> ()
in iter a
let ind_iter_references do_term do_cons do_type kn ind =
diff --git a/plugins/extraction/ocaml.ml b/plugins/extraction/ocaml.ml
index 96d8760404..8940aedd6d 100644
--- a/plugins/extraction/ocaml.ml
+++ b/plugins/extraction/ocaml.ml
@@ -310,6 +310,10 @@ let rec pp_expr par env args =
apply2
(v 0 (str "match " ++ head ++ str " with" ++ fnl () ++
pp_pat env pv))))
+ | MLuint i ->
+ assert (args=[]);
+ str "(" ++ str (Uint63.compile i) ++ str ")"
+
and pp_record_proj par env typ t pv args =
(* Can a match be printed as a mere record projection ? *)
diff --git a/plugins/extraction/scheme.ml b/plugins/extraction/scheme.ml
index 76a0c74068..6aa3a6220e 100644
--- a/plugins/extraction/scheme.ml
+++ b/plugins/extraction/scheme.ml
@@ -129,6 +129,8 @@ let rec pp_expr env args =
| MLmagic a ->
pp_expr env args a
| MLaxiom -> paren (str "error \"AXIOM TO BE REALIZED\"")
+ | MLuint _ ->
+ paren (str "Prelude.error \"EXTRACTION OF UINT NOT IMPLEMENTED\"")
and pp_cons_args env = function
| MLcons (_,r,args) when is_coinductive r ->
diff --git a/plugins/funind/functional_principles_proofs.ml b/plugins/funind/functional_principles_proofs.ml
index 3b95423067..8da30bd9c9 100644
--- a/plugins/funind/functional_principles_proofs.ml
+++ b/plugins/funind/functional_principles_proofs.ml
@@ -763,12 +763,13 @@ let build_proof
end
| Cast(t,_,_) ->
build_proof do_finalize {dyn_infos with info = t} g
- | Const _ | Var _ | Meta _ | Evar _ | Sort _ | Construct _ | Ind _ ->
+ | Const _ | Var _ | Meta _ | Evar _ | Sort _ | Construct _ | Ind _ | Int _ ->
do_finalize dyn_infos g
| App(_,_) ->
let f,args = decompose_app sigma dyn_infos.info in
begin
match EConstr.kind sigma f with
+ | Int _ -> user_err Pp.(str "integer cannot be applied")
| App _ -> assert false (* we have collected all the app in decompose_app *)
| Proj _ -> assert false (*FIXME*)
| Var _ | Construct _ | Rel _ | Evar _ | Meta _ | Ind _ | Sort _ | Prod _ ->
diff --git a/plugins/funind/g_indfun.mlg b/plugins/funind/g_indfun.mlg
index 8f0440a2a4..c4f8843e51 100644
--- a/plugins/funind/g_indfun.mlg
+++ b/plugins/funind/g_indfun.mlg
@@ -186,7 +186,7 @@ VERNAC COMMAND EXTEND Function
(Vernacexpr.(VernacExpr([], VernacFixpoint(Decl_kinds.NoDischarge, List.map snd recsl))))
with
| Vernacextend.VtSideff ids, _ when hard ->
- Vernacextend.(VtStartProof ("Classic", GuaranteesOpacity, ids), VtLater)
+ Vernacextend.(VtStartProof (GuaranteesOpacity, ids), VtLater)
| x -> x }
-> { do_generate_principle false (List.map snd recsl) }
END
diff --git a/plugins/funind/glob_term_to_relation.ml b/plugins/funind/glob_term_to_relation.ml
index 4b6caea70d..02964d7ba5 100644
--- a/plugins/funind/glob_term_to_relation.ml
+++ b/plugins/funind/glob_term_to_relation.ml
@@ -478,7 +478,7 @@ let rec build_entry_lc env funnames avoid rt : glob_constr build_entry_return =
observe (str " Entering : " ++ Printer.pr_glob_constr_env env rt);
let open CAst in
match DAst.get rt with
- | GRef _ | GVar _ | GEvar _ | GPatVar _ | GSort _ | GHole _ ->
+ | GRef _ | GVar _ | GEvar _ | GPatVar _ | GSort _ | GHole _ | GInt _ ->
(* do nothing (except changing type of course) *)
mk_result [] rt avoid
| GApp(_,_) ->
@@ -588,6 +588,7 @@ let rec build_entry_lc env funnames avoid rt : glob_constr build_entry_return =
build_entry_lc env funnames avoid (mkGApp(b,args))
| GRec _ -> user_err Pp.(str "Not handled GRec")
| GProd _ -> user_err Pp.(str "Cannot apply a type")
+ | GInt _ -> user_err Pp.(str "Cannot apply an integer")
end (* end of the application treatement *)
| GLambda(n,_,t,b) ->
@@ -1221,7 +1222,7 @@ let rebuild_cons env nb_args relname args crossed_types rt =
TODO: Find a valid way to deal with implicit arguments here!
*)
let rec compute_cst_params relnames params gt = DAst.with_val (function
- | GRef _ | GVar _ | GEvar _ | GPatVar _ -> params
+ | GRef _ | GVar _ | GEvar _ | GPatVar _ | GInt _ -> params
| GApp(f,args) ->
begin match DAst.get f with
| GVar relname' when Id.Set.mem relname' relnames ->
diff --git a/plugins/funind/glob_termops.ml b/plugins/funind/glob_termops.ml
index 5b45a8dbed..13ff19a46b 100644
--- a/plugins/funind/glob_termops.ml
+++ b/plugins/funind/glob_termops.ml
@@ -106,6 +106,7 @@ let change_vars =
| GRec _ -> user_err ?loc Pp.(str "Local (co)fixes are not supported")
| GSort _ as x -> x
| GHole _ as x -> x
+ | GInt _ as x -> x
| GCast(b,c) ->
GCast(change_vars mapping b,
Glob_ops.map_cast_type (change_vars mapping) c)
@@ -285,6 +286,7 @@ let rec alpha_rt excluded rt =
)
| GRec _ -> user_err Pp.(str "Not handled GRec")
| GSort _
+ | GInt _
| GHole _ as rt -> rt
| GCast (b,c) ->
GCast(alpha_rt excluded b,
@@ -344,6 +346,7 @@ let is_free_in id =
| GHole _ -> false
| GCast (b,(CastConv t|CastVM t|CastNative t)) -> is_free_in b || is_free_in t
| GCast (b,CastCoerce) -> is_free_in b
+ | GInt _ -> false
) x
and is_free_in_br {CAst.v=(ids,_,rt)} =
(not (Id.List.mem id ids)) && is_free_in rt
@@ -434,6 +437,7 @@ let replace_var_by_term x_id term =
| GRec _ -> raise (UserError(None,str "Not handled GRec"))
| GSort _
| GHole _ as rt -> rt
+ | GInt _ as rt -> rt
| GCast(b,c) ->
GCast(replace_var_by_pattern b,
Glob_ops.map_cast_type replace_var_by_pattern c)
@@ -516,7 +520,7 @@ let expand_as =
| PatCstr(_,patl,_) -> List.fold_left add_as map patl
in
let rec expand_as map = DAst.map (function
- | GRef _ | GEvar _ | GPatVar _ | GSort _ | GHole _ as rt -> rt
+ | GRef _ | GEvar _ | GPatVar _ | GSort _ | GHole _ | GInt _ as rt -> rt
| GVar id as rt ->
begin
try
diff --git a/plugins/funind/indfun.ml b/plugins/funind/indfun.ml
index 3a04c753ea..d9b0330e2b 100644
--- a/plugins/funind/indfun.ml
+++ b/plugins/funind/indfun.ml
@@ -201,7 +201,7 @@ let is_rec names =
let check_id id names = Id.Set.mem id names in
let rec lookup names gt = match DAst.get gt with
| GVar(id) -> check_id id names
- | GRef _ | GEvar _ | GPatVar _ | GSort _ | GHole _ -> false
+ | GRef _ | GEvar _ | GPatVar _ | GSort _ | GHole _ | GInt _ -> false
| GCast(b,_) -> lookup names b
| GRec _ -> error "GRec not handled"
| GIf(b,_,lhs,rhs) ->
diff --git a/plugins/funind/recdef.ml b/plugins/funind/recdef.ml
index 38f27f760b..1b5286dce4 100644
--- a/plugins/funind/recdef.ml
+++ b/plugins/funind/recdef.ml
@@ -306,6 +306,7 @@ let check_not_nested sigma forbidden e =
let rec check_not_nested e =
match EConstr.kind sigma e with
| Rel _ -> ()
+ | Int _ -> ()
| Var x ->
if Id.List.mem x forbidden
then user_err ~hdr:"Recdef.check_not_nested"
@@ -487,7 +488,7 @@ let rec travel_aux jinfo continuation_tac (expr_info:constr infos) g =
| _ -> anomaly (Pp.str "travel_aux : unexpected "++ Printer.pr_leconstr_env (pf_env g) sigma expr_info.info ++ Pp.str ".")
end
| Cast(t,_,_) -> travel jinfo continuation_tac {expr_info with info=t} g
- | Const _ | Var _ | Meta _ | Evar _ | Sort _ | Construct _ | Ind _ ->
+ | Const _ | Var _ | Meta _ | Evar _ | Sort _ | Construct _ | Ind _ | Int _ ->
let new_continuation_tac =
jinfo.otherS () expr_info continuation_tac in
new_continuation_tac expr_info g
@@ -1294,6 +1295,7 @@ let is_opaque_constant c =
| Declarations.OpaqueDef _ -> Proof_global.Opaque
| Declarations.Undef _ -> Proof_global.Opaque
| Declarations.Def _ -> Proof_global.Transparent
+ | Declarations.Primitive _ -> Proof_global.Opaque
let open_new_goal build_proof sigma using_lemmas ref_ goal_name (gls_type,decompose_and_tac,nb_goal) =
(* Pp.msgnl (str "gls_type := " ++ Printer.pr_lconstr gls_type); *)
diff --git a/plugins/ltac/g_ltac.mlg b/plugins/ltac/g_ltac.mlg
index d9b19c1ae6..4c24f51b1e 100644
--- a/plugins/ltac/g_ltac.mlg
+++ b/plugins/ltac/g_ltac.mlg
@@ -58,15 +58,8 @@ let new_entry name =
let toplevel_selector = new_entry "vernac:toplevel_selector"
let tacdef_body = new_entry "tactic:tacdef_body"
-(* Registers the Classic Proof Mode (which uses [tactic_mode] as a parser for
- proof editing and changes nothing else). Then sets it as the default proof mode. *)
-let _ =
- let mode = {
- Proof_global.name = "Classic";
- set = (fun () -> Pvernac.set_command_entry tactic_mode);
- reset = (fun () -> Pvernac.(set_command_entry noedit_mode));
- } in
- Proof_global.register_proof_mode mode
+(* Registers [tactic_mode] as a parser for proof editing *)
+let classic_proof_mode = Pvernac.register_proof_mode "Classic" tactic_mode
(* Hack to parse "[ id" without dropping [ *)
let test_bracket_ident =
diff --git a/plugins/ltac/g_obligations.mlg b/plugins/ltac/g_obligations.mlg
index 1ea6ff84d4..cdee012a82 100644
--- a/plugins/ltac/g_obligations.mlg
+++ b/plugins/ltac/g_obligations.mlg
@@ -83,7 +83,7 @@ open Obligations
let obligation obl tac = with_tac (fun t -> Obligations.obligation obl t) tac
let next_obligation obl tac = with_tac (fun t -> Obligations.next_obligation obl t) tac
-let classify_obbl _ = Vernacextend.(VtStartProof ("Classic",Doesn'tGuaranteeOpacity,[]), VtLater)
+let classify_obbl _ = Vernacextend.(VtStartProof (Doesn'tGuaranteeOpacity,[]), VtLater)
}
diff --git a/plugins/ltac/g_rewrite.mlg b/plugins/ltac/g_rewrite.mlg
index 31fb1c9abf..db8d1b20d8 100644
--- a/plugins/ltac/g_rewrite.mlg
+++ b/plugins/ltac/g_rewrite.mlg
@@ -285,13 +285,13 @@ VERNAC COMMAND EXTEND AddSetoid1 CLASSIFIED AS SIDEFF
add_morphism_infer atts m n;
}
| #[ atts = rewrite_attributes; ] [ "Add" "Morphism" constr(m) "with" "signature" lconstr(s) "as" ident(n) ]
- => { VtStartProof("Classic",GuaranteesOpacity,[n]), VtLater }
+ => { VtStartProof(GuaranteesOpacity,[n]), VtLater }
-> {
add_morphism atts [] m s n;
}
| #[ atts = rewrite_attributes; ] [ "Add" "Parametric" "Morphism" binders(binders) ":" constr(m)
"with" "signature" lconstr(s) "as" ident(n) ]
- => { VtStartProof("Classic",GuaranteesOpacity,[n]), VtLater }
+ => { VtStartProof(GuaranteesOpacity,[n]), VtLater }
-> {
add_morphism atts binders m s n;
}
diff --git a/plugins/ltac/g_tactic.mlg b/plugins/ltac/g_tactic.mlg
index 46ea3819ac..7bf705ffeb 100644
--- a/plugins/ltac/g_tactic.mlg
+++ b/plugins/ltac/g_tactic.mlg
@@ -287,10 +287,10 @@ GRAMMAR EXTEND Gram
[ [ c = smart_global; nl = occs -> { (nl,c) } ] ]
;
intropatterns:
- [ [ l = LIST0 nonsimple_intropattern -> { l } ] ]
+ [ [ l = LIST0 intropattern -> { l } ] ]
;
ne_intropatterns:
- [ [ l = LIST1 nonsimple_intropattern -> { l } ] ]
+ [ [ l = LIST1 intropattern -> { l } ] ]
;
or_and_intropattern:
[ [ "["; tc = LIST1 intropatterns SEP "|"; "]" -> { IntroOrPattern tc }
@@ -317,7 +317,7 @@ GRAMMAR EXTEND Gram
| "?" -> { IntroAnonymous }
| id = ident -> { IntroIdentifier id } ] ]
;
- nonsimple_intropattern:
+ intropattern:
[ [ l = simple_intropattern -> { l }
| "*" -> { CAst.make ~loc @@ IntroForthcoming true }
| "**" -> { CAst.make ~loc @@ IntroForthcoming false } ] ]
@@ -534,6 +534,8 @@ GRAMMAR EXTEND Gram
{ TacAtom (CAst.make ~loc @@ TacIntroPattern (false,[CAst.make ~loc @@IntroForthcoming false])) }
| IDENT "eintros"; pl = ne_intropatterns ->
{ TacAtom (CAst.make ~loc @@ TacIntroPattern (true,pl)) }
+ | IDENT "eintros" ->
+ { TacAtom (CAst.make ~loc @@ TacIntroPattern (true,[CAst.make ~loc @@IntroForthcoming false])) }
| IDENT "apply"; cl = LIST1 constr_with_bindings_arg SEP ",";
inhyp = in_hyp_as -> { TacAtom (CAst.make ~loc @@ TacApply (true,false,cl,inhyp)) }
diff --git a/plugins/micromega/coq_micromega.ml b/plugins/micromega/coq_micromega.ml
index d4bafe773f..7adae148bd 100644
--- a/plugins/micromega/coq_micromega.ml
+++ b/plugins/micromega/coq_micromega.ml
@@ -846,7 +846,7 @@ struct
match env with
| [] -> ([v],n)
| e::l ->
- if EConstr.eq_constr sigma e v
+ if EConstr.eq_constr_nounivs sigma e v
then (env,n)
else
let (env,n) = _add l ( n+1) v in
diff --git a/plugins/nsatz/Nsatz.v b/plugins/nsatz/Nsatz.v
index c5a09d677e..a964febf9c 100644
--- a/plugins/nsatz/Nsatz.v
+++ b/plugins/nsatz/Nsatz.v
@@ -452,6 +452,7 @@ constructor;red;intros;subst;trivial.
Qed.
Instance Rops: (@Ring_ops R 0%R 1%R Rplus Rmult Rminus Ropp (@eq R)).
+Defined.
Instance Rri : (Ring (Ro:=Rops)).
constructor;
@@ -468,6 +469,7 @@ Class can_compute_Z (z : Z) := dummy_can_compute_Z : True.
Hint Extern 0 (can_compute_Z ?v) =>
match isZcst v with true => exact I end : typeclass_instances.
Instance reify_IZR z lvar {_ : can_compute_Z z} : reify (PEc z) lvar (IZR z).
+Defined.
Lemma R_one_zero: 1%R <> 0%R.
discrR.
@@ -484,6 +486,7 @@ exact Rmult_integral. exact R_one_zero. Defined.
Require Import QArith.
Instance Qops: (@Ring_ops Q 0%Q 1%Q Qplus Qmult Qminus Qopp Qeq).
+Defined.
Instance Qri : (Ring (Ro:=Qops)).
constructor.
diff --git a/plugins/omega/PreOmega.v b/plugins/omega/PreOmega.v
index 94a3d40441..695f000cb1 100644
--- a/plugins/omega/PreOmega.v
+++ b/plugins/omega/PreOmega.v
@@ -12,6 +12,120 @@ Require Import Arith Max Min BinInt BinNat Znat Nnat.
Local Open Scope Z_scope.
+(** * [Z.div_mod_to_equations], [Z.quot_rem_to_equations], [Z.to_euclidean_division_equations]: the tactics for preprocessing [Z.div] and [Z.modulo], [Z.quot] and [Z.rem] *)
+
+(** These tactic use the complete specification of [Z.div] and
+ [Z.modulo] ([Z.quot] and [Z.rem], respectively) to remove these
+ functions from the goal without losing information. The
+ [Z.euclidean_division_equations_cleanup] tactic removes needless
+ hypotheses, which makes tactics like [nia] run faster. The tactic
+ [Z.to_euclidean_division_equations] combines the handling of both variants
+ of division/quotient and modulo/remainder. *)
+
+Module Z.
+ Lemma mod_0_r_ext x y : y = 0 -> x mod y = 0.
+ Proof. intro; subst; destruct x; reflexivity. Qed.
+ Lemma div_0_r_ext x y : y = 0 -> x / y = 0.
+ Proof. intro; subst; destruct x; reflexivity. Qed.
+
+ Lemma rem_0_r_ext x y : y = 0 -> Z.rem x y = x.
+ Proof. intro; subst; destruct x; reflexivity. Qed.
+ Lemma quot_0_r_ext x y : y = 0 -> Z.quot x y = 0.
+ Proof. intro; subst; destruct x; reflexivity. Qed.
+
+ Lemma rem_bound_pos_pos x y : 0 < y -> 0 <= x -> 0 <= Z.rem x y < y.
+ Proof. intros; apply Z.rem_bound_pos; assumption. Qed.
+ Lemma rem_bound_neg_pos x y : y < 0 -> 0 <= x -> 0 <= Z.rem x y < -y.
+ Proof. rewrite <- Z.rem_opp_r'; intros; apply Z.rem_bound_pos; rewrite ?Z.opp_pos_neg; assumption. Qed.
+ Lemma rem_bound_pos_neg x y : 0 < y -> x <= 0 -> -y < Z.rem x y <= 0.
+ Proof. rewrite <- (Z.opp_involutive x), Z.rem_opp_l', <- Z.opp_lt_mono, and_comm, !Z.opp_nonpos_nonneg; apply rem_bound_pos_pos. Qed.
+ Lemma rem_bound_neg_neg x y : y < 0 -> x <= 0 -> y < Z.rem x y <= 0.
+ Proof. rewrite <- (Z.opp_involutive x), <- (Z.opp_involutive y), Z.rem_opp_l', <- Z.opp_lt_mono, and_comm, !Z.opp_nonpos_nonneg, Z.opp_involutive; apply rem_bound_neg_pos. Qed.
+
+ Ltac div_mod_to_equations_generalize x y :=
+ pose proof (Z.div_mod x y);
+ pose proof (Z.mod_pos_bound x y);
+ pose proof (Z.mod_neg_bound x y);
+ pose proof (div_0_r_ext x y);
+ pose proof (mod_0_r_ext x y);
+ let q := fresh "q" in
+ let r := fresh "r" in
+ set (q := x / y) in *;
+ set (r := x mod y) in *;
+ clearbody q r.
+ Ltac quot_rem_to_equations_generalize x y :=
+ pose proof (Z.quot_rem' x y);
+ pose proof (rem_bound_pos_pos x y);
+ pose proof (rem_bound_pos_neg x y);
+ pose proof (rem_bound_neg_pos x y);
+ pose proof (rem_bound_neg_neg x y);
+ pose proof (quot_0_r_ext x y);
+ pose proof (rem_0_r_ext x y);
+ let q := fresh "q" in
+ let r := fresh "r" in
+ set (q := Z.quot x y) in *;
+ set (r := Z.rem x y) in *;
+ clearbody q r.
+
+ Ltac div_mod_to_equations_step :=
+ match goal with
+ | [ |- context[?x / ?y] ] => div_mod_to_equations_generalize x y
+ | [ |- context[?x mod ?y] ] => div_mod_to_equations_generalize x y
+ | [ H : context[?x / ?y] |- _ ] => div_mod_to_equations_generalize x y
+ | [ H : context[?x mod ?y] |- _ ] => div_mod_to_equations_generalize x y
+ end.
+ Ltac quot_rem_to_equations_step :=
+ match goal with
+ | [ |- context[Z.quot ?x ?y] ] => quot_rem_to_equations_generalize x y
+ | [ |- context[Z.rem ?x ?y] ] => quot_rem_to_equations_generalize x y
+ | [ H : context[Z.quot ?x ?y] |- _ ] => quot_rem_to_equations_generalize x y
+ | [ H : context[Z.rem ?x ?y] |- _ ] => quot_rem_to_equations_generalize x y
+ end.
+ Ltac div_mod_to_equations' := repeat div_mod_to_equations_step.
+ Ltac quot_rem_to_equations' := repeat quot_rem_to_equations_step.
+ Ltac euclidean_division_equations_cleanup :=
+ repeat match goal with
+ | [ H : ?x = ?x -> _ |- _ ] => specialize (H eq_refl)
+ | [ H : ?x <> ?x -> _ |- _ ] => clear H
+ | [ H : ?x < ?x -> _ |- _ ] => clear H
+ | [ H : ?T -> _, H' : ?T |- _ ] => specialize (H H')
+ | [ H : ?T -> _, H' : ~?T |- _ ] => clear H
+ | [ H : ~?T -> _, H' : ?T |- _ ] => clear H
+ | [ H : ?A -> ?x = ?x -> _ |- _ ] => specialize (fun a => H a eq_refl)
+ | [ H : ?A -> ?x <> ?x -> _ |- _ ] => clear H
+ | [ H : ?A -> ?x < ?x -> _ |- _ ] => clear H
+ | [ H : ?A -> ?B -> _, H' : ?B |- _ ] => specialize (fun a => H a H')
+ | [ H : ?A -> ?B -> _, H' : ~?B |- _ ] => clear H
+ | [ H : ?A -> ~?B -> _, H' : ?B |- _ ] => clear H
+ | [ H : 0 < ?x -> _, H' : ?x < 0 |- _ ] => clear H
+ | [ H : ?x < 0 -> _, H' : 0 < ?x |- _ ] => clear H
+ | [ H : ?A -> 0 < ?x -> _, H' : ?x < 0 |- _ ] => clear H
+ | [ H : ?A -> ?x < 0 -> _, H' : 0 < ?x |- _ ] => clear H
+ | [ H : 0 <= ?x -> _, H' : ?x < 0 |- _ ] => clear H
+ | [ H : ?x <= 0 -> _, H' : 0 < ?x |- _ ] => clear H
+ | [ H : ?A -> 0 <= ?x -> _, H' : ?x < 0 |- _ ] => clear H
+ | [ H : ?A -> ?x <= 0 -> _, H' : 0 < ?x |- _ ] => clear H
+ | [ H : 0 < ?x -> _, H' : ?x <= 0 |- _ ] => clear H
+ | [ H : ?x < 0 -> _, H' : 0 <= ?x |- _ ] => clear H
+ | [ H : ?A -> 0 < ?x -> _, H' : ?x <= 0 |- _ ] => clear H
+ | [ H : ?A -> ?x < 0 -> _, H' : 0 <= ?x |- _ ] => clear H
+ | [ H : 0 <= ?x -> _, H' : ?x <= 0 |- _ ] => specialize (fun pf => H (@Z.eq_le_incl 0 x (eq_sym pf)))
+ | [ H : ?A -> 0 <= ?x -> _, H' : ?x <= 0 |- _ ] => specialize (fun a pf => H a (@Z.eq_le_incl 0 x (eq_sym pf)))
+ | [ H : ?x <= 0 -> _, H' : 0 <= ?x |- _ ] => specialize (fun pf => H (@Z.eq_le_incl 0 x pf))
+ | [ H : ?A -> ?x <= 0 -> _, H' : 0 <= ?x |- _ ] => specialize (fun a pf => H a (@Z.eq_le_incl x 0 pf))
+ | [ H : ?x < ?y -> _, H' : ?x = ?y |- _ ] => clear H
+ | [ H : ?x < ?y -> _, H' : ?y = ?x |- _ ] => clear H
+ | [ H : ?A -> ?x < ?y -> _, H' : ?x = ?y |- _ ] => clear H
+ | [ H : ?A -> ?x < ?y -> _, H' : ?y = ?x |- _ ] => clear H
+ | [ H : ?x = ?y -> _, H' : ?x < ?y |- _ ] => clear H
+ | [ H : ?x = ?y -> _, H' : ?y < ?x |- _ ] => clear H
+ | [ H : ?A -> ?x = ?y -> _, H' : ?x < ?y |- _ ] => clear H
+ | [ H : ?A -> ?x = ?y -> _, H' : ?y < ?x |- _ ] => clear H
+ end.
+ Ltac div_mod_to_equations := div_mod_to_equations'; euclidean_division_equations_cleanup.
+ Ltac quot_rem_to_equations := quot_rem_to_equations'; euclidean_division_equations_cleanup.
+ Ltac to_euclidean_division_equations := div_mod_to_equations'; quot_rem_to_equations'; euclidean_division_equations_cleanup.
+End Z.
(** * zify: the Z-ification tactic *)
@@ -411,6 +525,24 @@ Ltac zify_N_op :=
| |- context [ Z.of_N (N.mul ?a ?b) ] =>
pose proof (N2Z.is_nonneg (N.mul a b)); rewrite (N2Z.inj_mul a b) in *
+ (* N.div -> Z.div and a positivity hypothesis *)
+ | H : context [ Z.of_N (N.div ?a ?b) ] |- _ =>
+ pose proof (N2Z.is_nonneg (N.div a b)); rewrite (N2Z.inj_div a b) in *
+ | |- context [ Z.of_N (N.div ?a ?b) ] =>
+ pose proof (N2Z.is_nonneg (N.div a b)); rewrite (N2Z.inj_div a b) in *
+
+ (* N.modulo -> Z.rem / Z.modulo and a positivity hypothesis (N.modulo agrees with Z.modulo on everything except 0; so we pose both the non-zero proof for this agreement, but also replace things with [Z.rem]) *)
+ | H : context [ Z.of_N (N.modulo ?a ?b) ] |- _ =>
+ pose proof (N2Z.is_nonneg (N.modulo a b));
+ pose proof (@Z.quot_div_nonneg (Z.of_N a) (Z.of_N b) (N2Z.is_nonneg a));
+ pose proof (@Z.rem_mod_nonneg (Z.of_N a) (Z.of_N b) (N2Z.is_nonneg a));
+ rewrite (N2Z.inj_rem a b) in *
+ | |- context [ Z.of_N (N.div ?a ?b) ] =>
+ pose proof (N2Z.is_nonneg (N.modulo a b));
+ pose proof (@Z.quot_div_nonneg (Z.of_N a) (Z.of_N b) (N2Z.is_nonneg a));
+ pose proof (@Z.rem_mod_nonneg (Z.of_N a) (Z.of_N b) (N2Z.is_nonneg a));
+ rewrite (N2Z.inj_rem a b) in *
+
(* atoms of type N : we add a positivity condition (if not already there) *)
| _ : 0 <= Z.of_N ?a |- _ => hide_Z_of_N a
| _ : context [ Z.of_N ?a ] |- _ => pose proof (N2Z.is_nonneg a); hide_Z_of_N a
diff --git a/plugins/setoid_ring/Ncring_initial.v b/plugins/setoid_ring/Ncring_initial.v
index 1ca6227f25..aa0370b2ac 100644
--- a/plugins/setoid_ring/Ncring_initial.v
+++ b/plugins/setoid_ring/Ncring_initial.v
@@ -32,6 +32,7 @@ Lemma Zsth : Equivalence (@eq Z).
Proof. exact Z.eq_equiv. Qed.
Instance Zops:@Ring_ops Z 0%Z 1%Z Z.add Z.mul Z.sub Z.opp (@eq Z).
+Defined.
Instance Zr: (@Ring _ _ _ _ _ _ _ _ Zops).
Proof.
diff --git a/plugins/setoid_ring/Ncring_tac.v b/plugins/setoid_ring/Ncring_tac.v
index 7958507819..c8d560cfe9 100644
--- a/plugins/setoid_ring/Ncring_tac.v
+++ b/plugins/setoid_ring/Ncring_tac.v
@@ -27,41 +27,50 @@ Class nth (R:Type) (t:R) (l:list R) (i:nat).
Instance Ifind0 (R:Type) (t:R) l
: nth t(t::l) 0.
+Defined.
Instance IfindS (R:Type) (t2 t1:R) l i
{_:nth t1 l i}
: nth t1 (t2::l) (S i) | 1.
+Defined.
Class closed (T:Type) (l:list T).
Instance Iclosed_nil T
: closed (T:=T) nil.
+Defined.
Instance Iclosed_cons T t (l:list T)
{_:closed l}
: closed (t::l).
+Defined.
Class reify (R:Type)`{Rr:Ring (T:=R)} (e:PExpr Z) (lvar:list R) (t:R).
Instance reify_zero (R:Type) lvar op
`{Ring (T:=R)(ring0:=op)}
: reify (ring0:=op)(PEc 0%Z) lvar op.
+Defined.
Instance reify_one (R:Type) lvar op
`{Ring (T:=R)(ring1:=op)}
: reify (ring1:=op) (PEc 1%Z) lvar op.
+Defined.
Instance reifyZ0 (R:Type) lvar
`{Ring (T:=R)}
: reify (PEc Z0) lvar Z0|11.
+Defined.
Instance reifyZpos (R:Type) lvar (p:positive)
`{Ring (T:=R)}
: reify (PEc (Zpos p)) lvar (Zpos p)|11.
+Defined.
Instance reifyZneg (R:Type) lvar (p:positive)
`{Ring (T:=R)}
: reify (PEc (Zneg p)) lvar (Zneg p)|11.
+Defined.
Instance reify_add (R:Type)
e1 lvar t1 e2 t2 op
@@ -69,6 +78,7 @@ Instance reify_add (R:Type)
{_:reify (add:=op) e1 lvar t1}
{_:reify (add:=op) e2 lvar t2}
: reify (add:=op) (PEadd e1 e2) lvar (op t1 t2).
+Defined.
Instance reify_mul (R:Type)
e1 lvar t1 e2 t2 op
@@ -76,6 +86,7 @@ Instance reify_mul (R:Type)
{_:reify (mul:=op) e1 lvar t1}
{_:reify (mul:=op) e2 lvar t2}
: reify (mul:=op) (PEmul e1 e2) lvar (op t1 t2)|10.
+Defined.
Instance reify_mul_ext (R:Type) `{Ring R}
lvar (z:Z) e2 t2
@@ -83,6 +94,7 @@ Instance reify_mul_ext (R:Type) `{Ring R}
{_:reify e2 lvar t2}
: reify (PEmul (PEc z) e2) lvar
(@multiplication Z _ _ z t2)|9.
+Defined.
Instance reify_sub (R:Type)
e1 lvar t1 e2 t2 op
@@ -90,24 +102,28 @@ Instance reify_sub (R:Type)
{_:reify (sub:=op) e1 lvar t1}
{_:reify (sub:=op) e2 lvar t2}
: reify (sub:=op) (PEsub e1 e2) lvar (op t1 t2).
+Defined.
Instance reify_opp (R:Type)
e1 lvar t1 op
`{Ring (T:=R)(opp:=op)}
{_:reify (opp:=op) e1 lvar t1}
: reify (opp:=op) (PEopp e1) lvar (op t1).
+Defined.
Instance reify_pow (R:Type) `{Ring R}
e1 lvar t1 n
`{Ring (T:=R)}
{_:reify e1 lvar t1}
: reify (PEpow e1 n) lvar (pow_N t1 n)|1.
+Defined.
Instance reify_var (R:Type) t lvar i
`{nth R t lvar i}
`{Rr: Ring (T:=R)}
: reify (Rr:= Rr) (PEX Z (Pos.of_succ_nat i))lvar t
| 100.
+Defined.
Class reifylist (R:Type)`{Rr:Ring (T:=R)} (lexpr:list (PExpr Z)) (lvar:list R)
(lterm:list R).
@@ -115,12 +131,14 @@ Class reifylist (R:Type)`{Rr:Ring (T:=R)} (lexpr:list (PExpr Z)) (lvar:list R)
Instance reify_nil (R:Type) lvar
`{Rr: Ring (T:=R)}
: reifylist (Rr:= Rr) nil lvar (@nil R).
+Defined.
Instance reify_cons (R:Type) e1 lvar t1 lexpr2 lterm2
`{Rr: Ring (T:=R)}
{_:reify (Rr:= Rr) e1 lvar t1}
{_:reifylist (Rr:= Rr) lexpr2 lvar lterm2}
: reifylist (Rr:= Rr) (e1::lexpr2) lvar (t1::lterm2).
+Defined.
Definition list_reifyl (R:Type) lexpr lvar lterm
`{Rr: Ring (T:=R)}
diff --git a/plugins/setoid_ring/Rings_Q.v b/plugins/setoid_ring/Rings_Q.v
index ae91ee1664..df3677e1c3 100644
--- a/plugins/setoid_ring/Rings_Q.v
+++ b/plugins/setoid_ring/Rings_Q.v
@@ -15,6 +15,7 @@ Require Export Integral_domain.
Require Import QArith.
Instance Qops: (@Ring_ops Q 0%Q 1%Q Qplus Qmult Qminus Qopp Qeq).
+Defined.
Instance Qri : (Ring (Ro:=Qops)).
constructor.
diff --git a/plugins/setoid_ring/Rings_R.v b/plugins/setoid_ring/Rings_R.v
index 901b36ed3b..fe7558845d 100644
--- a/plugins/setoid_ring/Rings_R.v
+++ b/plugins/setoid_ring/Rings_R.v
@@ -20,6 +20,7 @@ constructor;red;intros;subst;trivial.
Qed.
Instance Rops: (@Ring_ops R 0%R 1%R Rplus Rmult Rminus Ropp (@eq R)).
+Defined.
Instance Rri : (Ring (Ro:=Rops)).
constructor;
diff --git a/plugins/ssr/ssrast.mli b/plugins/ssr/ssrast.mli
index dd2c2d0ba4..9ce9250a43 100644
--- a/plugins/ssr/ssrast.mli
+++ b/plugins/ssr/ssrast.mli
@@ -67,7 +67,7 @@ type ssrview = ast_closure_term list
type id_block = Prefix of Id.t | SuffixId of Id.t | SuffixNum of int
(* Only [One] forces an introduction, possibly reducing the goal. *)
-type anon_iter =
+type anon_kind =
| One of string option (* name hint *)
| Drop
| All
@@ -76,25 +76,23 @@ type anon_iter =
type ssripat =
| IPatNoop
| IPatId of Id.t
- | IPatAnon of anon_iter (* inaccessible name *)
-(* TODO | IPatClearMark *)
- | IPatDispatch of bool (* ssr exception: accept a dispatch on the empty list even when there are subgoals *) * ssripatss_or_block (* (..|..) *)
- | IPatCase of (* ipats_mod option * *) ssripatss_or_block (* this is not equivalent to /case /[..|..] if there are already multiple goals *)
+ | IPatAnon of anon_kind (* inaccessible name *)
+ | IPatDispatch of ssripatss_or_block (* (..|..) *)
+ | IPatCase of ssripatss_or_block (* [..|..] *)
| IPatInj of ssripatss
| IPatRewrite of (*occurrence option * rewrite_pattern **) ssrocc * ssrdir
- | IPatView of bool * ssrview (* {}/view (true if the clear is present) *)
+ | IPatView of ssrview (* /view *)
| IPatClear of ssrclear (* {H1 H2} *)
| IPatSimpl of ssrsimpl
| IPatAbstractVars of Id.t list
| IPatFastNondep
- | IPatEqGen of unit Proofview.tactic (* internal use: generation of eqn *)
and ssripats = ssripat list
and ssripatss = ssripats list
and ssripatss_or_block =
| Block of id_block
| Regular of ssripats list
-type ssrhpats = ((ssrclear * ssripats) * ssripats) * ssripats
+type ssrhpats = ((ssrclear option * ssripats) * ssripats) * ssripats
type ssrhpats_wtransp = bool * ssrhpats
(* tac => inpats *)
diff --git a/plugins/ssr/ssrcommon.ml b/plugins/ssr/ssrcommon.ml
index 311d912efd..c3b9bde9b8 100644
--- a/plugins/ssr/ssrcommon.ml
+++ b/plugins/ssr/ssrcommon.ml
@@ -66,7 +66,7 @@ let check_hyp_exists hyps (SsrHyp(_, id)) =
try ignore(Context.Named.lookup id hyps)
with Not_found -> errorstrm Pp.(str"No assumption is named " ++ Id.print id)
-let test_hypname_exists hyps id =
+let test_hyp_exists hyps (SsrHyp(_, id)) =
try ignore(Context.Named.lookup id hyps); true
with Not_found -> false
diff --git a/plugins/ssr/ssrcommon.mli b/plugins/ssr/ssrcommon.mli
index 51116ccd75..e642b5e788 100644
--- a/plugins/ssr/ssrcommon.mli
+++ b/plugins/ssr/ssrcommon.mli
@@ -29,7 +29,7 @@ val allocc : ssrocc
val hyp_id : ssrhyp -> Id.t
val hyps_ids : ssrhyps -> Id.t list
val check_hyp_exists : ('a, 'b) Context.Named.pt -> ssrhyp -> unit
-val test_hypname_exists : ('a, 'b) Context.Named.pt -> Id.t -> bool
+val test_hyp_exists : ('a, 'b) Context.Named.pt -> ssrhyp -> bool
val check_hyps_uniq : Id.t list -> ssrhyps -> unit
val not_section_id : Id.t -> bool
val hyp_err : ?loc:Loc.t -> string -> Id.t -> 'a
diff --git a/plugins/ssr/ssrfwd.ml b/plugins/ssr/ssrfwd.ml
index 257ecd2a85..8c1363020a 100644
--- a/plugins/ssr/ssrfwd.ml
+++ b/plugins/ssr/ssrfwd.ml
@@ -94,17 +94,23 @@ let basecuttac name c gl =
let introstac ipats = Proofview.V82.of_tactic (tclIPAT ipats)
let havetac ist
- (transp,((((clr, pats), binders), simpl), (((fk, _), t), hint)))
+ (transp,((((clr, orig_pats), binders), simpl), (((fk, _), t), hint)))
suff namefst gl
=
let concl = pf_concl gl in
+ let pats = tclCompileIPats orig_pats in
+ let binders = tclCompileIPats binders in
+ let simpl = tclCompileIPats simpl in
let skols, pats =
- List.partition (function IPatAbstractVars _ -> true | _ -> false) pats in
+ List.partition (function IOpAbstractVars _ -> true | _ -> false) pats in
let itac_mkabs = introstac skols in
- let itac_c = introstac (IPatClear clr :: pats) in
+ let itac_c, clr =
+ match clr with
+ | None -> introstac pats, []
+ | Some clr -> introstac (tclCompileIPats (IPatClear clr :: orig_pats)), clr in
let itac, id, clr = introstac pats, Tacticals.tclIDTAC, old_cleartac clr in
let binderstac n =
- let rec aux = function 0 -> [] | n -> IPatAnon (One None) :: aux (n-1) in
+ let rec aux = function 0 -> [] | n -> IOpInaccessible None :: aux (n-1) in
Tacticals.tclTHEN (if binders <> [] then introstac (aux n) else Tacticals.tclIDTAC)
(introstac binders) in
let simpltac = introstac simpl in
@@ -160,7 +166,7 @@ let havetac ist
gl, ty, Tacticals.tclTHEN assert_is_conv (Proofview.V82.of_tactic (Tactics.apply t)), id, itac_c
| FwdHave, false, false ->
let skols = List.flatten (List.map (function
- | IPatAbstractVars ids -> ids
+ | IOpAbstractVars ids -> ids
| _ -> assert false) skols) in
let skols_args =
List.map (fun id -> Ssripats.Internal.examine_abstract (EConstr.mkVar id) gl) skols in
@@ -203,10 +209,12 @@ let destProd_or_LetIn sigma c =
| _ -> raise DestKO
let wlogtac ist (((clr0, pats),_),_) (gens, ((_, ct))) hint suff ghave gl =
+ let clr0 = Option.default [] clr0 in
+ let pats = tclCompileIPats pats in
let mkabs gen = abs_wgen false (fun x -> x) gen in
let mkclr gen clrs = clr_of_wgen gen clrs in
let mkpats = function
- | _, Some ((x, _), _) -> fun pats -> IPatId (hoi_id x) :: pats
+ | _, Some ((x, _), _) -> fun pats -> IOpId (hoi_id x) :: pats
| _ -> fun x -> x in
let ct = match Ssrcommon.ssrterm_of_ast_closure_term ct with
| (a, (b, Some ct)) ->
@@ -265,7 +273,7 @@ let wlogtac ist (((clr0, pats),_),_) (gens, ((_, ct))) hint suff ghave gl =
if gens = [] then errorstrm(str"gen have requires some generalizations");
let clear0 = old_cleartac clr0 in
let id, name_general_hyp, cleanup, pats = match id, pats with
- | None, (IPatId id as ip)::pats -> Some id, tacipat [ip], clear0, pats
+ | None, (IOpId id as ip)::pats -> Some id, tacipat [ip], clear0, pats
| None, _ -> None, Tacticals.tclIDTAC, clear0, pats
| Some (Some id),_ -> Some id, introid id, clear0, pats
| Some _,_ ->
@@ -289,6 +297,10 @@ let wlogtac ist (((clr0, pats),_),_) (gens, ((_, ct))) hint suff ghave gl =
(** The "suffice" tactic *)
let sufftac ist ((((clr, pats),binders),simpl), ((_, c), hint)) =
+ let clr = Option.default [] clr in
+ let pats = tclCompileIPats pats in
+ let binders = tclCompileIPats binders in
+ let simpl = tclCompileIPats simpl in
let htac = Tacticals.tclTHEN (introstac pats) (hinttac ist true hint) in
let c = match Ssrcommon.ssrterm_of_ast_closure_term c with
| (a, (b, Some ct)) ->
diff --git a/plugins/ssr/ssrfwd.mli b/plugins/ssr/ssrfwd.mli
index 8a05e25504..35e89dbcea 100644
--- a/plugins/ssr/ssrfwd.mli
+++ b/plugins/ssr/ssrfwd.mli
@@ -22,7 +22,7 @@ val ssrposetac : Id.t * (ssrfwdfmt * ast_closure_term) -> v82tac
val havetac : ist ->
bool *
- ((((Ssrast.ssrclear * Ssrast.ssripat list) * Ssrast.ssripats) *
+ ((((Ssrast.ssrclear option * Ssrast.ssripat list) * Ssrast.ssripats) *
Ssrast.ssripats) *
(((Ssrast.ssrfwdkind * 'a) * ast_closure_term) *
(bool * Tacinterp.Value.t option list))) ->
@@ -35,7 +35,7 @@ val basecuttac :
val wlogtac :
Ltac_plugin.Tacinterp.interp_sign ->
- ((Ssrast.ssrhyps * Ssrast.ssripats) * 'a) * 'b ->
+ ((Ssrast.ssrclear option * Ssrast.ssripats) * 'a) * 'b ->
(Ssrast.ssrhyps *
((Ssrast.ssrhyp_or_id * string) *
Ssrmatching_plugin.Ssrmatching.cpattern option)
@@ -50,7 +50,7 @@ val wlogtac :
val sufftac :
Ssrast.ist ->
- (((Ssrast.ssrhyps * Ssrast.ssripats) * Ssrast.ssripat list) *
+ (((Ssrast.ssrclear option * Ssrast.ssripats) * Ssrast.ssripat list) *
Ssrast.ssripat list) *
(('a *
ast_closure_term) *
diff --git a/plugins/ssr/ssripats.ml b/plugins/ssr/ssripats.ml
index ce81d83661..a8dfd69240 100644
--- a/plugins/ssr/ssripats.ml
+++ b/plugins/ssr/ssripats.ml
@@ -19,14 +19,78 @@ open Proofview.Notations
open Ssrast
+type ssriop =
+ | IOpId of Names.Id.t
+ | IOpDrop
+ | IOpTemporay
+ | IOpInaccessible of string option
+ | IOpInaccessibleAll
+ | IOpAbstractVars of Names.Id.t list
+ | IOpFastNondep
+
+ | IOpInj of ssriops list
+
+ | IOpDispatchBlock of id_block
+ | IOpDispatchBranches of ssriops list
+
+ | IOpCaseBlock of id_block
+ | IOpCaseBranches of ssriops list
+
+ | IOpRewrite of ssrocc * ssrdir
+ | IOpView of ssrclear option * ssrview (* extra clears to be performed *)
+
+ | IOpClear of ssrclear * ssrhyp option (* must clear, may clear *)
+ | IOpSimpl of ssrsimpl
+
+ | IOpEqGen of unit Proofview.tactic (* generation of eqn *)
+
+ | IOpNoop
+
+and ssriops = ssriop list
+
+let rec pr_ipatop = function
+ | IOpId id -> Names.Id.print id
+ | IOpDrop -> Pp.str "_"
+ | IOpTemporay -> Pp.str "+"
+ | IOpInaccessible None -> Pp.str "?"
+ | IOpInaccessible (Some s) -> Pp.str ("?«"^s^"»")
+ | IOpInaccessibleAll -> Pp.str "*"
+ | IOpAbstractVars l -> Pp.str ("[:"^String.concat " " (List.map Names.Id.to_string l)^"]")
+ | IOpFastNondep -> Pp.str ">"
+
+ | IOpInj l -> Pp.(str "[=" ++ ppl l ++ str "]")
+
+ | IOpDispatchBlock b -> Pp.(str"(" ++ Ssrprinters.pr_block b ++ str")")
+ | IOpDispatchBranches l -> Pp.(str "(" ++ ppl l ++ str ")")
+
+ | IOpCaseBlock b -> Pp.(str"[" ++ Ssrprinters.pr_block b ++ str"]")
+ | IOpCaseBranches l -> Pp.(str "[" ++ ppl l ++ str "]")
+
+ | IOpRewrite (occ,dir) -> Pp.(Ssrprinters.(pr_occ occ ++ pr_dir dir))
+ | IOpView (None,vs) -> Pp.(prlist_with_sep mt (fun c -> str "/" ++ Ssrprinters.pr_ast_closure_term c) vs)
+ | IOpView (Some cl,vs) -> Pp.(Ssrprinters.pr_clear Pp.spc cl ++ prlist_with_sep mt (fun c -> str "/" ++ Ssrprinters.pr_ast_closure_term c) vs)
+
+ | IOpClear (clmust,clmay) ->
+ Pp.(Ssrprinters.pr_clear spc clmust ++
+ match clmay with
+ | Some cl -> str "(try " ++ Ssrprinters.pr_clear spc [cl] ++ str")"
+ | None -> mt ())
+ | IOpSimpl s -> Ssrprinters.pr_simpl s
+
+ | IOpEqGen _ -> Pp.str "E:"
+ | IOpNoop -> Pp.str"-"
+and ppl x = Pp.(prlist_with_sep (fun () -> str"|") (prlist_with_sep spc pr_ipatop)) x
+
+
module IpatMachine : sig
(* the => tactical. ?eqtac is a tactic to be eventually run
* after the first [..] block. first_case_is_dispatch is the
* ssr exception to elim: and case: *)
val main : ?eqtac:unit tactic -> first_case_is_dispatch:bool ->
- ssripats -> unit tactic
+ ssriops -> unit tactic
+ val tclCompileIPats : ssripats -> ssriops
val tclSEED_SUBGOALS : Names.Name.t list array -> unit tactic -> unit tactic
@@ -53,7 +117,7 @@ module State : sig
val isNSEED_CONSUME : (Names.Name.t list option -> unit tactic) -> unit tactic
(* Some data may expire *)
- val isTICK : ssripat -> unit tactic
+ val isTICK : ssriop -> unit tactic
val isPRINT : Proofview.Goal.t -> Pp.t
@@ -149,7 +213,7 @@ let isNSEED_CONSUME k =
k x)
let isTICK = function
- | IPatSimpl _ | IPatClear _ -> tclUNIT ()
+ | IOpSimpl _ | IOpClear _ -> tclUNIT ()
| _ -> tclGET (fun s -> tclSET { s with name_seed = None })
end (* }}} *************************************************************** *)
@@ -238,6 +302,13 @@ let tacCHECK_HYPS_EXIST hyps = Goal.enter begin fun gl ->
tclUNIT ()
end
+let tacFILTER_HYP_EXIST hyps k = Goal.enter begin fun gl ->
+ let ctx = Goal.hyps gl in
+ k (Option.bind hyps (fun h ->
+ if Ssrcommon.test_hyp_exists ctx h &&
+ Ssrcommon.(not_section_id (hyp_id h)) then Some h else None))
+end
+
(** [=> []] *****************************************************************)
(* calls t1 then t2 on each subgoal passing to t2 the index of the current
@@ -286,13 +357,13 @@ let tac_intro_seed interp_ipats fix = Goal.enter begin fun gl ->
| Prefix id -> Id.to_string id ^ "?"
| SuffixNum n -> "?" ^ string_of_int n
| SuffixId id -> "?" ^ Id.to_string id in
- IPatAnon (One (Some s))
+ IOpInaccessible (Some s)
| Name id ->
let s = match fix with
| Prefix fix -> Id.to_string fix ^ Id.to_string id
| SuffixNum n -> Id.to_string id ^ string_of_int n
| SuffixId fix -> Id.to_string id ^ Id.to_string fix in
- IPatId (Id.of_string s)) seeds in
+ IOpId (Id.of_string s)) seeds in
interp_ipats ipats
end end
@@ -342,7 +413,7 @@ let tclMK_ABSTRACT_VARS ids =
(* Debugging *)
let tclLOG p t =
tclUNIT () >>= begin fun () ->
- Ssrprinters.ppdebug (lazy Pp.(str "exec: " ++ Ssrprinters.pr_ipat p));
+ Ssrprinters.ppdebug (lazy Pp.(str "exec: " ++ pr_ipatop p));
tclUNIT ()
end <*>
Goal.enter begin fun g ->
@@ -362,58 +433,74 @@ let tclLOG p t =
let notTAC = tclUNIT false
+let duplicate_clear =
+ CWarnings.create ~name:"duplicate-clear" ~category:"ssr"
+ (fun id -> Pp.(str "Duplicate clear of " ++ Id.print id))
+
(* returns true if it was a tactic (eg /ltac:tactic) *)
let rec ipat_tac1 ipat : bool tactic =
match ipat with
- | IPatView (clear_if_id,l) ->
+ | IOpView (glued_clear,l) ->
+ let clear_if_id, extra_clear =
+ match glued_clear with
+ | None -> false, []
+ | Some x -> true, List.map Ssrcommon.hyp_id x in
Ssrview.tclIPAT_VIEWS
~views:l ~clear_if_id
- ~conclusion:(fun ~to_clear:clr -> intro_clear clr)
+ ~conclusion:(fun ~to_clear:clr ->
+ let inter = CList.intersect Id.equal clr extra_clear in
+ List.iter duplicate_clear inter;
+ let cl = CList.union Id.equal clr extra_clear in
+ intro_clear cl)
- | IPatDispatch(true, Regular [[]]) ->
- notTAC
- | IPatDispatch(_, Regular ipatss) ->
+ | IOpDispatchBranches ipatss ->
tclDISPATCH (List.map ipat_tac ipatss) <*> notTAC
- | IPatDispatch(_,Block id_block) ->
+ | IOpDispatchBlock id_block ->
tac_intro_seed ipat_tac id_block <*> notTAC
-
- | IPatId id -> Ssrcommon.tclINTRO_ID id <*> notTAC
- | IPatFastNondep -> intro_anon_deps <*> notTAC
-
- | IPatCase (Block id_block) ->
+ | IOpCaseBlock id_block ->
Ssrcommon.tclWITHTOP tac_case <*> tac_intro_seed ipat_tac id_block <*> notTAC
- | IPatCase (Regular ipatss) ->
+ | IOpCaseBranches ipatss ->
tclIORPAT (Ssrcommon.tclWITHTOP tac_case) ipatss <*> notTAC
- | IPatInj ipatss ->
+
+ | IOpId id -> Ssrcommon.tclINTRO_ID id <*> notTAC
+ | IOpFastNondep -> intro_anon_deps <*> notTAC
+ | IOpDrop -> intro_drop <*> notTAC
+ | IOpInaccessible seed -> Ssrcommon.tclINTRO_ANON ?seed () <*> notTAC
+ | IOpInaccessibleAll -> intro_anon_all <*> notTAC
+ | IOpTemporay -> intro_anon_temp <*> notTAC
+
+ | IOpSimpl Nop -> assert false
+
+ | IOpInj ipatss ->
tclIORPAT (Ssrcommon.tclWITHTOP
(fun t -> V82.tactic ~nf_evars:false (Ssrelim.perform_injection t)))
ipatss
<*> notTAC
- | IPatAnon Drop -> intro_drop <*> notTAC
- | IPatAnon (One seed) -> Ssrcommon.tclINTRO_ANON ?seed () <*> notTAC
- | IPatAnon All -> intro_anon_all <*> notTAC
- | IPatAnon Temporary -> intro_anon_temp <*> notTAC
-
- | IPatNoop -> notTAC
- | IPatSimpl Nop -> notTAC
-
- | IPatClear ids ->
- tacCHECK_HYPS_EXIST ids <*>
- intro_clear (List.map Ssrcommon.hyp_id ids) <*>
+ | IOpClear (must,may) ->
+ tacCHECK_HYPS_EXIST must <*>
+ tacFILTER_HYP_EXIST may (fun may ->
+ let must = List.map Ssrcommon.hyp_id must in
+ let cl = Option.fold_left (fun cls (SsrHyp(_,id)) ->
+ if CList.mem_f Id.equal id cls then begin
+ duplicate_clear id;
+ cls
+ end else id :: cls) must may in
+ intro_clear cl) <*>
notTAC
- | IPatSimpl x ->
+ | IOpSimpl x ->
V82.tactic ~nf_evars:false (Ssrequality.simpltac x) <*> notTAC
- | IPatRewrite (occ,dir) ->
+ | IOpRewrite (occ,dir) ->
Ssrcommon.tclWITHTOP
(fun x -> V82.tactic ~nf_evars:false (Ssrequality.ipat_rewrite occ dir x)) <*> notTAC
- | IPatAbstractVars ids -> tclMK_ABSTRACT_VARS ids <*> notTAC
+ | IOpAbstractVars ids -> tclMK_ABSTRACT_VARS ids <*> notTAC
- | IPatEqGen t -> t <*> notTAC
+ | IOpEqGen t -> t <*> notTAC
+ | IOpNoop -> notTAC
and ipat_tac pl : unit tactic =
match pl with
@@ -433,51 +520,88 @@ and tclIORPAT tac = function
| p -> Tacticals.New.tclTHENS tac (List.map ipat_tac p)
and ssr_exception is_on = function
- | Some (IPatCase l) when is_on -> Some (IPatDispatch(true, l))
+ | Some (IOpCaseBranches [[]]) when is_on -> Some IOpNoop
+ | Some (IOpCaseBranches l) when is_on ->
+ Some (IOpDispatchBranches l)
+ | Some (IOpCaseBlock s) when is_on ->
+ Some (IOpDispatchBlock s)
| x -> x
and option_to_list = function None -> [] | Some x -> [x]
and split_at_first_case ipats =
let rec loop acc = function
- | (IPatSimpl _ | IPatClear _) as x :: rest -> loop (x :: acc) rest
- | (IPatCase _ | IPatDispatch _) as x :: xs -> CList.rev acc, Some x, xs
+ | (IOpSimpl _ | IOpClear _) as x :: rest -> loop (x :: acc) rest
+ | (IOpCaseBlock _ | IOpCaseBranches _
+ | IOpDispatchBlock _ | IOpDispatchBranches _) as x :: xs ->
+ CList.rev acc, Some x, xs
| pats -> CList.rev acc, None, pats
in
loop [] ipats
;;
(* Simple pass doing {x}/v -> /v{x} *)
-let elaborate_ipats l =
+let tclCompileIPats l =
let rec elab = function
+
+ | (IPatClear cl) :: (IPatView v) :: rest ->
+ (IOpView(Some cl,v)) :: elab rest
+ | (IPatClear cl) :: (IPatId id) :: rest ->
+ (IOpClear (cl,Some (SsrHyp(None,id)))) :: IOpId id :: elab rest
+
+ (* boring code *)
| [] -> []
- | (IPatClear _ as p1) :: (IPatView _ as p2) :: rest -> p2 :: p1 :: elab rest
- | IPatDispatch(s, Regular p) :: rest -> IPatDispatch (s, Regular (List.map elab p)) :: elab rest
- | IPatCase (Regular p) :: rest -> IPatCase (Regular (List.map elab p)) :: elab rest
- | IPatInj p :: rest -> IPatInj (List.map elab p) :: elab rest
- | (IPatEqGen _ | IPatId _ | IPatSimpl _ | IPatClear _ | IPatFastNondep |
- IPatAnon _ | IPatView _ | IPatNoop | IPatRewrite _ |
- IPatAbstractVars _ | IPatDispatch(_, Block _) | IPatCase(Block _)) as x :: rest -> x :: elab rest
- in
- elab l
-let main ?eqtac ~first_case_is_dispatch ipats =
- let ipats = elaborate_ipats ipats in
- let ip_before, case, ip_after = split_at_first_case ipats in
+ | IPatId id :: rest -> IOpId id :: elab rest
+ | IPatAnon (One hint) ::rest -> IOpInaccessible hint :: elab rest
+ | IPatAnon Drop :: rest -> IOpDrop :: elab rest
+ | IPatAnon All :: rest -> IOpInaccessibleAll :: elab rest
+ | IPatAnon Temporary :: rest -> IOpTemporay :: elab rest
+ | IPatAbstractVars vs :: rest -> IOpAbstractVars vs :: elab rest
+ | IPatFastNondep :: rest -> IOpFastNondep :: elab rest
+
+ | IPatInj pats :: rest -> IOpInj (List.map elab pats) :: elab rest
+ | IPatRewrite(occ,dir) :: rest -> IOpRewrite(occ,dir) :: elab rest
+ | IPatView vs :: rest -> IOpView (None,vs) :: elab rest
+ | IPatSimpl s :: rest -> IOpSimpl s :: elab rest
+ | IPatClear cl :: rest -> IOpClear (cl,None) :: elab rest
+
+ | IPatCase (Block seed) :: rest -> IOpCaseBlock seed :: elab rest
+ | IPatCase (Regular bs) :: rest -> IOpCaseBranches (List.map elab bs) :: elab rest
+ | IPatDispatch (Block seed) :: rest -> IOpDispatchBlock seed :: elab rest
+ | IPatDispatch (Regular bs) :: rest -> IOpDispatchBranches (List.map elab bs) :: elab rest
+ | IPatNoop :: rest -> IOpNoop :: elab rest
+
+ in
+ elab l
+;;
+let tclCompileIPats l =
+ Ssrprinters.ppdebug (lazy Pp.(str "tclCompileIPats input: " ++
+ prlist_with_sep spc Ssrprinters.pr_ipat l));
+ let ops = tclCompileIPats l in
+ Ssrprinters.ppdebug (lazy Pp.(str "tclCompileIPats output: " ++
+ prlist_with_sep spc pr_ipatop ops));
+ ops
+
+let main ?eqtac ~first_case_is_dispatch iops =
+ let ip_before, case, ip_after = split_at_first_case iops in
let case = ssr_exception first_case_is_dispatch case in
let case = option_to_list case in
- let eqtac = option_to_list (Option.map (fun x -> IPatEqGen x) eqtac) in
- Ssrcommon.tcl0G ~default:() (ipat_tac (ip_before @ case @ eqtac @ ip_after) <*> intro_end)
+ let eqtac = option_to_list (Option.map (fun x -> IOpEqGen x) eqtac) in
+ let ipats = ip_before @ case @ eqtac @ ip_after in
+ Ssrcommon.tcl0G ~default:() (ipat_tac ipats <*> intro_end)
end (* }}} *)
let tclIPAT_EQ eqtac ip =
Ssrprinters.ppdebug (lazy Pp.(str "ipat@run: " ++ Ssrprinters.pr_ipats ip));
- IpatMachine.main ~eqtac ~first_case_is_dispatch:true ip
+ IpatMachine.(main ~eqtac ~first_case_is_dispatch:true (tclCompileIPats ip))
let tclIPATssr ip =
Ssrprinters.ppdebug (lazy Pp.(str "ipat@run: " ++ Ssrprinters.pr_ipats ip));
- IpatMachine.main ~first_case_is_dispatch:true ip
+ IpatMachine.(main ~first_case_is_dispatch:true (tclCompileIPats ip))
+
+let tclCompileIPats = IpatMachine.tclCompileIPats
(* Common code to handle generalization lists along with the defective case *)
let with_defective maintac deps clr = Goal.enter begin fun g ->
@@ -721,12 +845,12 @@ let eqmovetac _ gen =
;;
let rec eqmoveipats eqpat = function
- | (IPatSimpl _ | IPatClear _ as ipat) :: ipats ->
+ | (IOpSimpl _ | IOpClear _ as ipat) :: ipats ->
ipat :: eqmoveipats eqpat ipats
- | (IPatAnon All :: _ | []) as ipats ->
- IPatAnon (One None) :: eqpat :: ipats
+ | (IOpInaccessibleAll :: _ | []) as ipats ->
+ IOpInaccessible None :: eqpat @ ipats
| ipat :: ipats ->
- ipat :: eqpat :: ipats
+ ipat :: eqpat @ ipats
let ssrsmovetac = Goal.enter begin fun g ->
let sigma, concl = Goal.(sigma g, concl g) in
@@ -736,7 +860,6 @@ let ssrsmovetac = Goal.enter begin fun g ->
end
let tclIPAT ip =
- Ssrprinters.ppdebug (lazy Pp.(str "ipat@run: " ++ Ssrprinters.pr_ipats ip));
IpatMachine.main ~first_case_is_dispatch:false ip
let ssrmovetac = function
@@ -748,17 +871,17 @@ let ssrmovetac = function
gentac <*>
tclLAST_GEN ~to_ind:false lastgen
(tacVIEW_THEN_GRAB view ~conclusion) <*>
- tclIPAT (IPatClear clr :: ipats)
+ tclIPAT (IOpClear (clr,None) :: IpatMachine.tclCompileIPats ipats)
| _::_ as view, (_, ({ gens = []; clr }, ipats)) ->
- tclIPAT (IPatView (false,view) :: IPatClear clr :: ipats)
+ tclIPAT (IOpView (None,view) :: IOpClear (clr,None) :: IpatMachine.tclCompileIPats ipats)
| _, (Some pat, (dgens, ipats)) ->
let dgentac = with_dgens dgens eqmovetac in
- dgentac <*> tclIPAT (eqmoveipats pat ipats)
+ dgentac <*> tclIPAT (eqmoveipats (IpatMachine.tclCompileIPats [pat]) (IpatMachine.tclCompileIPats ipats))
| _, (_, ({ gens = (_ :: _ as gens); dgens = []; clr}, ipats)) ->
let gentac = V82.tactic ~nf_evars:false (Ssrcommon.genstac (gens, clr)) in
- gentac <*> tclIPAT ipats
+ gentac <*> tclIPAT (IpatMachine.tclCompileIPats ipats)
| _, (_, ({ clr }, ipats)) ->
- Tacticals.New.tclTHENLIST [ssrsmovetac; Tactics.clear (List.map Ssrcommon.hyp_id clr); tclIPAT ipats]
+ Tacticals.New.tclTHENLIST [ssrsmovetac; Tactics.clear (List.map Ssrcommon.hyp_id clr); tclIPAT (IpatMachine.tclCompileIPats ipats)]
(** [abstract: absvar gens] **************************************************)
let rec is_Evar_or_CastedMeta sigma x =
diff --git a/plugins/ssr/ssripats.mli b/plugins/ssr/ssripats.mli
index 89cba4be71..893061b154 100644
--- a/plugins/ssr/ssripats.mli
+++ b/plugins/ssr/ssripats.mli
@@ -19,8 +19,44 @@
open Ssrast
+(* Atomic operations for the IPat machine. Use this if you are "patching" an
+ * ipat written by the user, since patching it at he AST level and then
+ * compiling it may have tricky effects, eg adding a clear in front of a view
+ * also has the effect of disposing the view (the compilation phase takes care
+ * of this, by using the compiled ipats you can be more precise *)
+type ssriop =
+ | IOpId of Names.Id.t
+ | IOpDrop
+ | IOpTemporay
+ | IOpInaccessible of string option
+ | IOpInaccessibleAll
+ | IOpAbstractVars of Names.Id.t list
+ | IOpFastNondep
+
+ | IOpInj of ssriops list
+
+ | IOpDispatchBlock of id_block
+ | IOpDispatchBranches of ssriops list
+
+ | IOpCaseBlock of id_block
+ | IOpCaseBranches of ssriops list
+
+ | IOpRewrite of ssrocc * ssrdir
+ | IOpView of ssrclear option * ssrview (* extra clears to be performed *)
+
+ | IOpClear of ssrclear * ssrhyp option
+ | IOpSimpl of ssrsimpl
+
+ | IOpEqGen of unit Proofview.tactic (* generation of eqn *)
+
+ | IOpNoop
+
+and ssriops = ssriop list
+
+val tclCompileIPats : ssripats -> ssriops
+
(* The => tactical *)
-val tclIPAT : ssripats -> unit Proofview.tactic
+val tclIPAT : ssriops -> unit Proofview.tactic
(* As above but with the SSR exception: first case is dispatch *)
val tclIPATssr : ssripats -> unit Proofview.tactic
diff --git a/plugins/ssr/ssrparser.mlg b/plugins/ssr/ssrparser.mlg
index 76726009ac..3fb21e5ef6 100644
--- a/plugins/ssr/ssrparser.mlg
+++ b/plugins/ssr/ssrparser.mlg
@@ -635,11 +635,10 @@ let rec map_ipat map_id map_ssrhyp map_ast_closure_term = function
| IPatClear clr -> IPatClear (List.map map_ssrhyp clr)
| IPatCase (Regular iorpat) -> IPatCase (Regular (List.map (List.map (map_ipat map_id map_ssrhyp map_ast_closure_term)) iorpat))
| IPatCase (Block(hat)) -> IPatCase (Block(map_block map_id hat))
- | IPatDispatch (s, Regular iorpat) -> IPatDispatch (s, Regular (List.map (List.map (map_ipat map_id map_ssrhyp map_ast_closure_term)) iorpat))
- | IPatDispatch (s, Block (hat)) -> IPatDispatch (s, Block(map_block map_id hat))
+ | IPatDispatch (Regular iorpat) -> IPatDispatch (Regular (List.map (List.map (map_ipat map_id map_ssrhyp map_ast_closure_term)) iorpat))
+ | IPatDispatch (Block (hat)) -> IPatDispatch (Block(map_block map_id hat))
| IPatInj iorpat -> IPatInj (List.map (List.map (map_ipat map_id map_ssrhyp map_ast_closure_term)) iorpat)
- | IPatView (clr,v) -> IPatView (clr,List.map map_ast_closure_term v)
- | IPatEqGen _ -> assert false (*internal usage only *)
+ | IPatView v -> IPatView (List.map map_ast_closure_term v)
and map_block map_id = function
| Prefix id -> Prefix (map_id id)
| SuffixId id -> SuffixId (map_id id)
@@ -715,22 +714,22 @@ let interp_ipat ist gl =
if not (ltacvar id) then hyp :: hyps else
add_intro_pattern_hyps CAst.(make ?loc (interp_introid ist gl id)) hyps in
let clr' = List.fold_right add_hyps clr [] in
- check_hyps_uniq [] clr'; IPatClear clr'
+ check_hyps_uniq [] clr';
+ IPatClear clr'
| IPatCase(Regular iorpat) ->
IPatCase(Regular(List.map (List.map interp) iorpat))
| IPatCase(Block(hat)) -> IPatCase(Block(interp_block hat))
- | IPatDispatch(s,Regular iorpat) ->
- IPatDispatch(s,Regular (List.map (List.map interp) iorpat))
- | IPatDispatch(s,Block(hat)) -> IPatDispatch(s,Block(interp_block hat))
+ | IPatDispatch(Regular iorpat) ->
+ IPatDispatch(Regular (List.map (List.map interp) iorpat))
+ | IPatDispatch(Block(hat)) -> IPatDispatch(Block(interp_block hat))
| IPatInj iorpat -> IPatInj (List.map (List.map interp) iorpat)
| IPatAbstractVars l ->
IPatAbstractVars (List.map get_intro_id (List.map (interp_introid ist gl) l))
- | IPatView (clr,l) -> IPatView (clr,List.map (fun x -> snd(interp_ast_closure_term ist
+ | IPatView l -> IPatView (List.map (fun x -> snd(interp_ast_closure_term ist
gl x)) l)
| (IPatSimpl _ | IPatAnon _ | IPatRewrite _ | IPatNoop | IPatFastNondep) as x -> x
- | IPatEqGen _ -> assert false (*internal usage only *)
in
interp
@@ -765,10 +764,6 @@ ARGUMENT EXTEND ssripat TYPED AS ssripatrep list PRINTED BY { pr_ssripats }
| Some [], _ -> CErrors.user_err ~loc (str"occ_switch expected")
| None, occ -> [IPatRewrite (occ, R2L)]
| Some clr, _ -> [IPatClear clr; IPatRewrite (allocc, R2L)] }
- | [ ssrdocc(occ) ssrfwdview(v) ] -> { match occ with
- | Some [], _ -> [IPatView (true,v)]
- | Some cl, _ -> check_hyps_uniq [] cl; [IPatClear cl;IPatView (false,v)]
- | _ -> CErrors.user_err ~loc (str"Only identifiers are allowed here") }
| [ ssrdocc(occ) ] -> { match occ with
| Some cl, _ -> check_hyps_uniq [] cl; [IPatClear cl]
| _ -> CErrors.user_err ~loc (str"Only identifiers are allowed here") }
@@ -786,7 +781,7 @@ ARGUMENT EXTEND ssripat TYPED AS ssripatrep list PRINTED BY { pr_ssripats }
| [ "-/" integer(n) "/=" ] -> { [IPatNoop;IPatSimpl(SimplCut (n,~-1))] }
| [ "-/" integer(n) "/" integer (m) "=" ] ->
{ [IPatNoop;IPatSimpl(SimplCut(n,m))] }
- | [ ssrfwdview(v) ] -> { [IPatView (false,v)] }
+ | [ ssrfwdview(v) ] -> { [IPatView v] }
| [ "[" ":" ident_list(idl) "]" ] -> { [IPatAbstractVars idl] }
| [ "[:" ident_list(idl) "]" ] -> { [IPatAbstractVars idl] }
END
@@ -875,11 +870,12 @@ ARGUMENT EXTEND ssripats_ne TYPED AS ssripat PRINTED BY { pr_ssripats }
let check_ssrhpats loc w_binders ipats =
let err_loc s = CErrors.user_err ~loc ~hdr:"ssreflect" s in
let clr, ipats =
+ let opt_app = function None -> fun l -> Some l
+ | Some l1 -> fun l2 -> Some (l1 @ l2) in
let rec aux clr = function
- | IPatClear cl :: tl -> aux (clr @ cl) tl
-(* | IPatSimpl (cl, sim) :: tl -> clr @ cl, IPatSimpl ([], sim) :: tl *)
+ | IPatClear cl :: tl -> aux (opt_app clr cl) tl
| tl -> clr, tl
- in aux [] ipats in
+ in aux None ipats in
let simpl, ipats =
match List.rev ipats with
| IPatSimpl _ as s :: tl -> [s], List.rev tl
@@ -903,27 +899,29 @@ let check_ssrhpats loc w_binders ipats =
in loop [] ipats in
((clr, ipat), binders), simpl
+let pr_clear_opt sep = function None -> mt () | Some x -> pr_clear sep x
+
let pr_hpats (((clr, ipat), binders), simpl) =
- pr_clear mt clr ++ pr_ipats ipat ++ pr_ipats binders ++ pr_ipats simpl
+ pr_clear_opt mt clr ++ pr_ipats ipat ++ pr_ipats binders ++ pr_ipats simpl
let pr_ssrhpats _ _ _ = pr_hpats
let pr_ssrhpats_wtransp _ _ _ (_, x) = pr_hpats x
}
-ARGUMENT EXTEND ssrhpats TYPED AS (((ssrclear * ssripat) * ssripat) * ssripat)
+ARGUMENT EXTEND ssrhpats TYPED AS (((ssrclear option * ssripat) * ssripat) * ssripat)
PRINTED BY { pr_ssrhpats }
| [ ssripats(i) ] -> { check_ssrhpats loc true i }
END
ARGUMENT EXTEND ssrhpats_wtransp
- TYPED AS (bool * (((ssrclear * ssripats) * ssripats) * ssripats))
+ TYPED AS (bool * (((ssrclear option * ssripats) * ssripats) * ssripats))
PRINTED BY { pr_ssrhpats_wtransp }
| [ ssripats(i) ] -> { false,check_ssrhpats loc true i }
| [ ssripats(i) "@" ssripats(j) ] -> { true,check_ssrhpats loc true (i @ j) }
END
ARGUMENT EXTEND ssrhpats_nobs
-TYPED AS (((ssrclear * ssripats) * ssripats) * ssripats) PRINTED BY { pr_ssrhpats }
+TYPED AS (((ssrclear option * ssripats) * ssripats) * ssripats) PRINTED BY { pr_ssrhpats }
| [ ssripats(i) ] -> { check_ssrhpats loc false i }
END
@@ -2051,7 +2049,7 @@ END
(* We just add a numeric version that clears the n top assumptions. *)
TACTIC EXTEND ssrclear
- | [ "clear" natural(n) ] -> { tclIPAT (List.init n (fun _ -> IPatAnon Drop)) }
+ | [ "clear" natural(n) ] -> { tclIPAT (List.init n (fun _ -> IOpDrop)) }
END
(** The "move" tactic *)
@@ -2090,10 +2088,10 @@ let movearg_of_parsed_movearg (v,(eq,(dg,ip))) =
TACTIC EXTEND ssrmove
| [ "move" ssrmovearg(arg) ssrrpat(pat) ] ->
- { ssrmovetac (movearg_of_parsed_movearg arg) <*> tclIPAT [pat] }
+ { ssrmovetac (movearg_of_parsed_movearg arg) <*> tclIPAT (tclCompileIPats [pat]) }
| [ "move" ssrmovearg(arg) ssrclauses(clauses) ] ->
{ tclCLAUSES (ssrmovetac (movearg_of_parsed_movearg arg)) clauses }
-| [ "move" ssrrpat(pat) ] -> { tclIPAT [pat] }
+| [ "move" ssrrpat(pat) ] -> { tclIPAT (tclCompileIPats [pat]) }
| [ "move" ] -> { ssrsmovetac }
END
@@ -2632,7 +2630,11 @@ END
{
-let augment_preclr clr1 (((clr0, x),y),z) = (((clr1 @ clr0, x),y),z)
+let augment_preclr clr1 (((clr0, x),y),z) =
+ let cl = match clr0 with
+ | None -> if clr1 = [] then None else Some clr1
+ | Some clr0 -> Some (clr1 @ clr0) in
+ (((cl, x),y),z)
}
diff --git a/plugins/ssr/ssrprinters.ml b/plugins/ssr/ssrprinters.ml
index 898e03b00e..38f5b7d107 100644
--- a/plugins/ssr/ssrprinters.ml
+++ b/plugins/ssr/ssrprinters.ml
@@ -74,7 +74,7 @@ let pr_occ = function
| None -> str "{}"
let pr_clear_ne clr = str "{" ++ pr_hyps clr ++ str "}"
-let pr_clear sep clr = if clr = [] then mt () else sep () ++ pr_clear_ne clr
+let pr_clear sep clr = sep () ++ pr_clear_ne clr
let pr_dir = function L2R -> str "->" | R2L -> str "<-"
@@ -102,20 +102,18 @@ let rec pr_ipat p =
| IPatClear clr -> pr_clear mt clr
| IPatCase (Regular iorpat) -> hov 1 (str "[" ++ pr_iorpat iorpat ++ str "]")
| IPatCase (Block m) -> hov 1 (str"[" ++ pr_block m ++ str"]")
- | IPatDispatch(_,Regular iorpat) -> hov 1 (str "(" ++ pr_iorpat iorpat ++ str ")")
- | IPatDispatch (_,Block m) -> hov 1 (str"(" ++ pr_block m ++ str")")
+ | IPatDispatch(Regular iorpat) -> hov 1 (str "(" ++ pr_iorpat iorpat ++ str ")")
+ | IPatDispatch (Block m) -> hov 1 (str"(" ++ pr_block m ++ str")")
| IPatInj iorpat -> hov 1 (str "[=" ++ pr_iorpat iorpat ++ str "]")
| IPatRewrite (occ, dir) -> pr_occ occ ++ pr_dir dir
| IPatAnon All -> str "*"
| IPatAnon Drop -> str "_"
| IPatAnon (One _) -> str "?"
- | IPatView (false,v) -> pr_view2 v
- | IPatView (true,v) -> str"{}" ++ pr_view2 v
+ | IPatView v -> pr_view2 v
| IPatAnon Temporary -> str "+"
| IPatNoop -> str "-"
| IPatAbstractVars l -> str "[:" ++ pr_list spc Id.print l ++ str "]"
| IPatFastNondep -> str">"
- | IPatEqGen _ -> str "<tac>"
and pr_ipats ipats = pr_list spc pr_ipat ipats
and pr_iorpat iorpat = pr_list pr_bar pr_ipats iorpat
and pr_block = function (Prefix id) -> str"^" ++ Id.print id
diff --git a/plugins/ssr/ssrprinters.mli b/plugins/ssr/ssrprinters.mli
index 31c360ad6d..5f20ac2705 100644
--- a/plugins/ssr/ssrprinters.mli
+++ b/plugins/ssr/ssrprinters.mli
@@ -43,6 +43,7 @@ val pr_view2 : ast_closure_term list -> Pp.t
val pr_ipat : ssripat -> Pp.t
val pr_ipats : ssripats -> Pp.t
val pr_iorpat : ssripatss -> Pp.t
+val pr_block : id_block -> Pp.t
val pr_hyp : ssrhyp -> Pp.t
val pr_hyps : ssrhyps -> Pp.t
diff --git a/plugins/ssr/ssrview.ml b/plugins/ssr/ssrview.ml
index 4816027296..2794696017 100644
--- a/plugins/ssr/ssrview.ml
+++ b/plugins/ssr/ssrview.ml
@@ -142,7 +142,7 @@ let intern_constr_expr { Genintern.genv; ltacvars = vars } sigma ce =
To allow for t being a notation, like "Notation foo x := ltac:(foo x)", we
need to internalize t.
*)
-let is_tac_in_term ?extra_scope { body; glob_env; interp_env } =
+let is_tac_in_term ?extra_scope { annotation; body; glob_env; interp_env } =
Goal.(enter_one ~__LOC__ begin fun goal ->
let genv = env goal in
let sigma = sigma goal in
@@ -161,7 +161,7 @@ let is_tac_in_term ?extra_scope { body; glob_env; interp_env } =
| Glob_term.GHole (_,_, Some x)
when Genarg.has_type x (Genarg.glbwit Tacarg.wit_tactic)
-> tclUNIT (`Tac (Genarg.out_gen (Genarg.glbwit Tacarg.wit_tactic) x))
- | _ -> tclUNIT (`Term (interp_env, g))
+ | _ -> tclUNIT (`Term (annotation, interp_env, g))
end)
(* To inject a constr into a glob_constr we use an Ltac variable *)
@@ -207,7 +207,7 @@ let tclKeepOpenConstr (_env, sigma, t) = Unsafe.tclEVARS sigma <*> tclUNIT t
let tclADD_CLEAR_IF_ID (env, ist, t) x =
Ssrprinters.ppdebug (lazy
Pp.(str"tclADD_CLEAR_IF_ID: " ++ Printer.pr_econstr_env env ist t));
- let hd, _ = EConstr.decompose_app ist t in
+ let hd, args = EConstr.decompose_app ist t in
match EConstr.kind ist hd with
| Constr.Var id when Ssrcommon.not_section_id id -> tclUNIT (x, [id])
| _ -> tclUNIT (x,[])
@@ -280,8 +280,9 @@ let interp_view ~clear_if_id ist v p =
else tclKeepOpenConstr ot >>= tclPAIR []
(* we store in the state (v top), then (v1 (v2 top))... *)
-let pile_up_view ~clear_if_id (ist, v) =
+let pile_up_view ~clear_if_id (annotation, ist, v) =
let ist = Ssrcommon.option_assert_get ist (Pp.str"not a term") in
+ let clear_if_id = clear_if_id && annotation <> `Parens in
State.vsPUSH (fun p -> interp_view ~clear_if_id ist v p)
let finalize_view s0 ?(simple_types=true) p =
diff --git a/plugins/ssrmatching/ssrmatching.ml b/plugins/ssrmatching/ssrmatching.ml
index efd65ade15..552a4048b1 100644
--- a/plugins/ssrmatching/ssrmatching.ml
+++ b/plugins/ssrmatching/ssrmatching.ml
@@ -312,7 +312,8 @@ let iter_constr_LR f c = match kind c with
| Fix (_, (_, t, b)) | CoFix (_, (_, t, b)) ->
for i = 0 to Array.length t - 1 do f t.(i); f b.(i) done
| Proj(_,a) -> f a
- | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _) -> ()
+ | (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _ | Construct _
+ | Int _) -> ()
(* The comparison used to determine which subterms matches is KEYED *)
(* CONVERSION. This looks for convertible terms that either have the same *)
diff --git a/plugins/syntax/int31_syntax.ml b/plugins/syntax/int31_syntax.ml
deleted file mode 100644
index e34a401c2c..0000000000
--- a/plugins/syntax/int31_syntax.ml
+++ /dev/null
@@ -1,114 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-
-(* Poor's man DECLARE PLUGIN *)
-let __coq_plugin_name = "int31_syntax_plugin"
-let () = Mltop.add_known_module __coq_plugin_name
-
-(* digit-based syntax for int31 *)
-
-open Bigint
-open Names
-open Globnames
-open Glob_term
-
-(*** Constants for locating int31 constructors ***)
-
-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 make_mind mp id = Names.MutInd.make2 mp (Label.make id)
-let make_mind_mpfile dir id = make_mind (ModPath.MPfile (make_dir dir)) id
-let make_mind_mpdot dir modname id =
- let mp = ModPath.MPdot (ModPath.MPfile (make_dir dir), Label.make modname)
- in make_mind mp id
-
-
-(* int31 stuff *)
-let int31_module = ["Coq"; "Numbers"; "Cyclic"; "Int31"; "Int31"]
-let int31_path = make_path int31_module "int31"
-let int31_id = make_mind_mpfile int31_module
-let int31_scope = "int31_scope"
-
-let int31_construct = ConstructRef ((int31_id "int31",0),1)
-
-let int31_0 = ConstructRef ((int31_id "digits",0),1)
-let int31_1 = ConstructRef ((int31_id "digits",0),2)
-
-(*** Definition of the Non_closed exception, used in the pretty printing ***)
-exception Non_closed
-
-(*** Parsing for int31 in digital notation ***)
-
-(* parses a *non-negative* integer (from bigint.ml) into an int31
- wraps modulo 2^31 *)
-let int31_of_pos_bigint ?loc n =
- let ref_construct = DAst.make ?loc (GRef (int31_construct, None)) in
- let ref_0 = DAst.make ?loc (GRef (int31_0, None)) in
- let ref_1 = DAst.make ?loc (GRef (int31_1, None)) in
- let rec args counter n =
- if counter <= 0 then
- []
- else
- let (q,r) = div2_with_rest n in
- (if r then ref_1 else ref_0)::(args (counter-1) q)
- in
- DAst.make ?loc (GApp (ref_construct, List.rev (args 31 n)))
-
-let error_negative ?loc =
- CErrors.user_err ?loc ~hdr:"interp_int31" (Pp.str "int31 are only non-negative numbers.")
-
-let interp_int31 ?loc n =
- if is_pos_or_zero n then
- int31_of_pos_bigint ?loc n
- else
- error_negative ?loc
-
-(* Pretty prints an int31 *)
-
-let bigint_of_int31 =
- let rec args_parsing args cur =
- match args with
- | [] -> cur
- | r::l when is_gr r int31_0 -> args_parsing l (mult_2 cur)
- | r::l when is_gr r int31_1 -> args_parsing l (add_1 (mult_2 cur))
- | _ -> raise Non_closed
- in
- fun c -> match DAst.get c with
- | GApp (r, args) when is_gr r int31_construct -> args_parsing args zero
- | _ -> raise Non_closed
-
-let uninterp_int31 (AnyGlobConstr i) =
- try
- Some (bigint_of_int31 i)
- with Non_closed ->
- None
-
-open Notation
-
-let at_declare_ml_module f x =
- Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
-
-(* Actually declares the interpreter for int31 *)
-
-let _ =
- register_bignumeral_interpretation int31_scope (interp_int31,uninterp_int31);
- at_declare_ml_module enable_prim_token_interpretation
- { pt_local = false;
- pt_scope = int31_scope;
- pt_interp_info = Uid int31_scope;
- pt_required = (int31_path,int31_module);
- pt_refs = [int31_construct];
- pt_in_match = true }
diff --git a/plugins/syntax/int31_syntax_plugin.mlpack b/plugins/syntax/int31_syntax_plugin.mlpack
deleted file mode 100644
index 54a5bc0cd1..0000000000
--- a/plugins/syntax/int31_syntax_plugin.mlpack
+++ /dev/null
@@ -1 +0,0 @@
-Int31_syntax
diff --git a/plugins/syntax/int63_syntax.ml b/plugins/syntax/int63_syntax.ml
new file mode 100644
index 0000000000..992b7a986b
--- /dev/null
+++ b/plugins/syntax/int63_syntax.ml
@@ -0,0 +1,55 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2017 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+
+(* Poor's man DECLARE PLUGIN *)
+let __coq_plugin_name = "int63_syntax_plugin"
+let () = Mltop.add_known_module __coq_plugin_name
+
+(* digit-based syntax for int63 *)
+
+open Names
+open Libnames
+
+(*** Constants for locating int63 constructors ***)
+
+let q_int63 = qualid_of_string "Coq.Numbers.Cyclic.Int63.Int63.int"
+let q_id_int63 = qualid_of_string "Coq.Numbers.Cyclic.Int63.Int63.id_int"
+
+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)
+
+(* int63 stuff *)
+let int63_module = ["Coq"; "Numbers"; "Cyclic"; "Int63"; "Int63"]
+let int63_path = make_path int63_module "int"
+let int63_scope = "int63_scope"
+
+let at_declare_ml_module f x =
+ Mltop.declare_cache_obj (fun () -> f x) __coq_plugin_name
+
+(* Actually declares the interpreter for int63 *)
+
+let _ =
+ let open Notation in
+ at_declare_ml_module
+ (fun () ->
+ let id_int63 = Nametab.locate q_id_int63 in
+ let o = { to_kind = Int63, Direct;
+ to_ty = id_int63;
+ of_kind = Int63, Direct;
+ of_ty = id_int63;
+ ty_name = q_int63;
+ warning = Nop } in
+ enable_prim_token_interpretation
+ { pt_local = false;
+ pt_scope = int63_scope;
+ pt_interp_info = NumeralNotation o;
+ pt_required = (int63_path, int63_module);
+ pt_refs = [];
+ pt_in_match = false })
+ ()
diff --git a/plugins/syntax/int63_syntax_plugin.mlpack b/plugins/syntax/int63_syntax_plugin.mlpack
new file mode 100644
index 0000000000..d83d554fe6
--- /dev/null
+++ b/plugins/syntax/int63_syntax_plugin.mlpack
@@ -0,0 +1 @@
+Int63_syntax
diff --git a/plugins/syntax/numeral.ml b/plugins/syntax/numeral.ml
index 470deb4a60..0c6d2ac0d1 100644
--- a/plugins/syntax/numeral.ml
+++ b/plugins/syntax/numeral.ml
@@ -33,30 +33,49 @@ let get_constructors ind =
Array.to_list
(Array.mapi (fun j c -> ConstructRef (ind, j + 1)) mc)
-let q_z = qualid_of_string "Coq.Numbers.BinNums.Z"
-let q_positive = qualid_of_string "Coq.Numbers.BinNums.positive"
-let q_int = qualid_of_string "Coq.Init.Decimal.int"
-let q_uint = qualid_of_string "Coq.Init.Decimal.uint"
-let q_option = qualid_of_string "Coq.Init.Datatypes.option"
+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
| IndRef i -> i
| _ -> raise Not_found
-let locate_ind q =
- try unsafe_locate_ind q
- with Not_found -> Nametab.error_global_not_found q
-
let locate_z () =
- try
- Some { z_ty = unsafe_locate_ind q_z;
- pos_ty = unsafe_locate_ind q_positive }
- with Not_found -> None
+ 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_int () =
- { uint = locate_ind q_uint;
- int = locate_ind q_int }
+ let int = "num.int.type" in
+ let uint = "num.uint.type" in
+ if Coqlib.has_ref int && Coqlib.has_ref uint
+ then
+ let q_int = qualid_of_ref int in
+ let q_uint = qualid_of_ref uint in
+ Some ({
+ int = unsafe_locate_ind q_int;
+ uint = unsafe_locate_ind q_uint;
+ }, mkRefC q_int, mkRefC q_uint)
+ 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 f ty =
let (sigma, env) = Pfedit.get_current_context () in
@@ -64,65 +83,65 @@ let has_type f ty =
try let _ = Constrintern.interp_constr env sigma c in true
with Pretype_errors.PretypeError _ -> false
-let type_error_to f ty loadZ =
+let type_error_to f ty =
CErrors.user_err
(pr_qualid f ++ str " should go from Decimal.int to " ++
pr_qualid ty ++ str " or (option " ++ pr_qualid ty ++ str ")." ++
- fnl () ++ str "Instead of Decimal.int, the types Decimal.uint or Z could be used" ++
- (if loadZ then str " (require BinNums first)." else str "."))
+ fnl () ++ str "Instead of Decimal.int, the types Decimal.uint or Z or Int63.int could be used (you may need to require BinNums or Decimal or Int63 first).")
-let type_error_of g ty loadZ =
+let type_error_of g ty =
CErrors.user_err
(pr_qualid g ++ str " should go from " ++ pr_qualid ty ++
str " to Decimal.int or (option Decimal.int)." ++ fnl () ++
- str "Instead of Decimal.int, the types Decimal.uint or Z could be used" ++
- (if loadZ then str " (require BinNums first)." else str "."))
+ str "Instead of Decimal.int, the types Decimal.uint or Z or Int63.int could be used (you may need to require BinNums or Decimal or Int63 first).")
let vernac_numeral_notation local ty f g scope opts =
let int_ty = locate_int () 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 cref q = mkRefC q in
let arrow x y =
mkProdC ([CAst.make Anonymous],Default Decl_kinds.Explicit, x, y)
in
- let cZ = cref q_z in
- let cint = cref q_int in
- let cuint = cref q_uint in
- let coption = cref q_option in
- let opt r = app coption r in
+ let opt r = app (mkRefC (q_option ())) r in
let constructors = get_constructors tyc in
(* Check the type of f *)
let to_kind =
- if has_type f (arrow cint cty) then Int int_ty, Direct
- else if has_type f (arrow cint (opt cty)) then Int int_ty, Option
- else if has_type f (arrow cuint cty) then UInt int_ty.uint, Direct
- else if has_type f (arrow cuint (opt cty)) then UInt int_ty.uint, Option
- else
- match z_pos_ty with
- | Some z_pos_ty ->
- if has_type f (arrow cZ cty) then Z z_pos_ty, Direct
- else if has_type f (arrow cZ (opt cty)) then Z z_pos_ty, Option
- else type_error_to f ty false
- | None -> type_error_to f ty true
+ match int_ty with
+ | Some (int_ty, cint, _) when has_type f (arrow cint cty) -> Int int_ty, Direct
+ | Some (int_ty, cint, _) when has_type f (arrow cint (opt cty)) -> Int int_ty, Option
+ | Some (int_ty, _, cuint) when has_type f (arrow cuint cty) -> UInt int_ty.uint, Direct
+ | Some (int_ty, _, cuint) when has_type f (arrow cuint (opt cty)) -> UInt int_ty.uint, Option
+ | _ ->
+ match z_pos_ty with
+ | Some (z_pos_ty, cZ) when has_type f (arrow cZ cty) -> Z z_pos_ty, Direct
+ | Some (z_pos_ty, cZ) when has_type f (arrow cZ (opt cty)) -> Z z_pos_ty, Option
+ | _ ->
+ match int63_ty with
+ | Some cint63 when has_type f (arrow cint63 cty) -> Int63, Direct
+ | Some cint63 when has_type f (arrow cint63 (opt cty)) -> Int63, Option
+ | _ -> type_error_to f ty
in
(* Check the type of g *)
let of_kind =
- if has_type g (arrow cty cint) then Int int_ty, Direct
- else if has_type g (arrow cty (opt cint)) then Int int_ty, Option
- else if has_type g (arrow cty cuint) then UInt int_ty.uint, Direct
- else if has_type g (arrow cty (opt cuint)) then UInt int_ty.uint, Option
- else
- match z_pos_ty with
- | Some z_pos_ty ->
- if has_type g (arrow cty cZ) then Z z_pos_ty, Direct
- else if has_type g (arrow cty (opt cZ)) then Z z_pos_ty, Option
- else type_error_of g ty false
- | None -> type_error_of g ty true
+ match int_ty with
+ | Some (int_ty, cint, _) when has_type g (arrow cty cint) -> Int int_ty, Direct
+ | Some (int_ty, cint, _) when has_type g (arrow cty (opt cint)) -> Int int_ty, Option
+ | Some (int_ty, _, cuint) when has_type g (arrow cty cuint) -> UInt int_ty.uint, Direct
+ | Some (int_ty, _, cuint) when has_type g (arrow cty (opt cuint)) -> UInt int_ty.uint, Option
+ | _ ->
+ match z_pos_ty with
+ | Some (z_pos_ty, cZ) when has_type g (arrow cty cZ) -> Z z_pos_ty, Direct
+ | Some (z_pos_ty, cZ) when has_type g (arrow cty (opt cZ)) -> Z z_pos_ty, Option
+ | _ ->
+ match int63_ty with
+ | Some cint63 when has_type g (arrow cty cint63) -> Int63, Direct
+ | Some cint63 when has_type g (arrow cty (opt cint63)) -> Int63, Option
+ | _ -> type_error_of g ty
in
let o = { to_kind; to_ty; of_kind; of_ty;
ty_name = ty;
diff --git a/plugins/syntax/plugin_base.dune b/plugins/syntax/plugin_base.dune
index 1ab16c700d..aac46338ea 100644
--- a/plugins/syntax/plugin_base.dune
+++ b/plugins/syntax/plugin_base.dune
@@ -20,8 +20,8 @@
(libraries coq.vernac))
(library
- (name int31_syntax_plugin)
- (public_name coq.plugins.int31_syntax)
- (synopsis "Coq syntax plugin: int31")
- (modules int31_syntax)
+ (name int63_syntax_plugin)
+ (public_name coq.plugins.int63_syntax)
+ (synopsis "Coq syntax plugin: int63")
+ (modules int63_syntax)
(libraries coq.vernac))
diff --git a/pretyping/arguments_renaming.ml b/pretyping/arguments_renaming.ml
index 0ace11839e..08df9a2460 100644
--- a/pretyping/arguments_renaming.ml
+++ b/pretyping/arguments_renaming.ml
@@ -43,7 +43,7 @@ let subst_rename_args (subst, (_, (r, names as orig))) =
if r==r' then orig else (r', names)
let discharge_rename_args = function
- | _, (ReqGlobal (c, names), _ as req) ->
+ | _, (ReqGlobal (c, names), _ as req) when not (isVarRef c && Lib.is_in_section c) ->
(try
let vars = Lib.variable_section_segment_of_reference c in
let var_names = List.map (fst %> NamedDecl.get_id %> Name.mk_name) vars in
diff --git a/pretyping/cbv.ml b/pretyping/cbv.ml
index f8289f558c..e27fc536eb 100644
--- a/pretyping/cbv.ml
+++ b/pretyping/cbv.ml
@@ -38,6 +38,10 @@ open Esubst
* the bindings S, and then applied to args. Here again,
* weak reduction.
* CONSTR(c,args) is the constructor [c] applied to [args].
+ * PRIMITIVE(cop,args) represent a particial application of
+ * a primitive, or a fully applied primitive
+ * which does not reduce.
+ * cop is the constr representing op.
*
*)
type cbv_value =
@@ -48,6 +52,7 @@ type cbv_value =
| FIXP of fixpoint * cbv_value subs * cbv_value array
| COFIXP of cofixpoint * cbv_value subs * cbv_value array
| CONSTR of constructor Univ.puniverses * cbv_value array
+ | PRIMITIVE of CPrimitives.t * constr * cbv_value array
(* type of terms with a hole. This hole can appear only under App or Case.
* TOP means the term is considered without context
@@ -90,6 +95,9 @@ let rec shift_value n = function
COFIXP (cofix,subs_shft (n,s), Array.map (shift_value n) args)
| CONSTR (c,args) ->
CONSTR (c, Array.map (shift_value n) args)
+ | PRIMITIVE(op,c,args) ->
+ PRIMITIVE(op,c,Array.map (shift_value n) args)
+
let shift_value n v =
if Int.equal n 0 then v else shift_value n v
@@ -109,10 +117,11 @@ let contract_cofixp env (i,(_,_,bds as bodies)) =
let n = Array.length bds in
subs_cons(Array.init n make_body, env), bds.(i)
-let make_constr_ref n = function
+let make_constr_ref n k t =
+ match k with
| RelKey p -> mkRel (n+p)
- | VarKey id -> mkVar id
- | ConstKey cst -> mkConstU cst
+ | VarKey id -> t
+ | ConstKey cst -> t
(* Adds an application list. Collapse APPs! *)
let stack_app appl stack =
@@ -136,7 +145,7 @@ let mkSTACK = function
type cbv_infos = {
env : Environ.env;
- tab : cbv_value KeyTable.t;
+ tab : cbv_value Declarations.constant_def KeyTable.t;
reds : RedFlags.reds;
sigma : Evd.evar_map
}
@@ -159,7 +168,8 @@ let strip_appl head stack =
| FIXP (fix,env,app) -> (FIXP(fix,env,[||]), stack_app app stack)
| COFIXP (cofix,env,app) -> (COFIXP(cofix,env,[||]), stack_app app stack)
| CONSTR (c,app) -> (CONSTR(c,[||]), stack_app app stack)
- | _ -> (head, stack)
+ | PRIMITIVE(op,c,app) -> (PRIMITIVE(op,c,[||]), stack_app app stack)
+ | VAL _ | STACK _ | CBN _ | LAM _ -> (head, stack)
(* Tests if fixpoint reduction is possible. *)
@@ -189,6 +199,60 @@ let get_debug_cbv = Goptions.declare_bool_option_and_ref
~name:"cbv visited constants display"
~key:["Debug";"Cbv"]
+(* Reduction of primitives *)
+
+open Primred
+
+module VNativeEntries =
+ struct
+
+ type elem = cbv_value
+ type args = cbv_value array
+ type evd = unit
+
+ let get = Array.get
+
+ let get_int () e =
+ match e with
+ | VAL(_, ci) ->
+ (match kind ci with
+ | Int i -> i
+ | _ -> raise Primred.NativeDestKO)
+ | _ -> raise Primred.NativeDestKO
+
+ let mkInt env i = VAL(0, mkInt i)
+
+ let mkBool env b =
+ let (ct,cf) = get_bool_constructors env in
+ CONSTR(Univ.in_punivs (if b then ct else cf), [||])
+
+ let int_ty env = VAL(0, mkConst @@ get_int_type env)
+
+ let mkCarry env b e =
+ let (c0,c1) = get_carry_constructors env in
+ CONSTR(Univ.in_punivs (if b then c1 else c0), [|int_ty env;e|])
+
+ let mkIntPair env e1 e2 =
+ let int_ty = int_ty env in
+ let c = get_pair_constructor env in
+ CONSTR(Univ.in_punivs c, [|int_ty;int_ty;e1;e2|])
+
+ let mkLt env =
+ let (_eq,lt,_gt) = get_cmp_constructors env in
+ CONSTR(Univ.in_punivs lt, [||])
+
+ let mkEq env =
+ let (eq,_lt,_gt) = get_cmp_constructors env in
+ CONSTR(Univ.in_punivs eq, [||])
+
+ let mkGt env =
+ let (_eq,_lt,gt) = get_cmp_constructors env in
+ CONSTR(Univ.in_punivs gt, [||])
+
+ end
+
+module VredNative = RedNative(VNativeEntries)
+
let debug_pr_key = function
| ConstKey (sp,_) -> Names.Constant.print sp
| VarKey id -> Names.Id.print id
@@ -225,6 +289,8 @@ and reify_value = function (* reduction under binders *)
mkApp (apply_env env cofix, Array.map reify_value args)
| CONSTR (c,args) ->
mkApp(mkConstructU c, Array.map reify_value args)
+ | PRIMITIVE(op,c,args) ->
+ mkApp(c, Array.map reify_value args)
and apply_env env t =
match kind t with
@@ -277,14 +343,14 @@ let rec norm_head info env t stack =
| Inl (0,v) -> strip_appl v stack
| Inl (n,v) -> strip_appl (shift_value n v) stack
| Inr (n,None) -> (VAL(0, mkRel n), stack)
- | Inr (n,Some p) -> norm_head_ref (n-p) info env stack (RelKey p))
+ | Inr (n,Some p) -> norm_head_ref (n-p) info env stack (RelKey p) t)
- | Var id -> norm_head_ref 0 info env stack (VarKey id)
+ | Var id -> norm_head_ref 0 info env stack (VarKey id) t
| Const sp ->
Reductionops.reduction_effect_hook info.env info.sigma
(fst sp) (lazy (reify_stack t stack));
- norm_head_ref 0 info env stack (ConstKey sp)
+ norm_head_ref 0 info env stack (ConstKey sp) t
| LetIn (_, b, _, c) ->
(* zeta means letin are contracted; delta without zeta means we *)
@@ -315,22 +381,23 @@ let rec norm_head info env t stack =
| Construct c -> (CONSTR(c, [||]), stack)
(* neutral cases *)
- | (Sort _ | Meta _ | Ind _) -> (VAL(0, t), stack)
+ | (Sort _ | Meta _ | Ind _ | Int _) -> (VAL(0, t), stack)
| Prod _ -> (CBN(t,env), stack)
-and norm_head_ref k info env stack normt =
+and norm_head_ref k info env stack normt t =
if red_set_ref info.reds normt then
match cbv_value_cache info normt with
- | Some body ->
+ | Declarations.Def body ->
if get_debug_cbv () then Feedback.msg_debug Pp.(str "Unfolding " ++ debug_pr_key normt);
strip_appl (shift_value k body) stack
- | None ->
+ | Declarations.Primitive op -> (PRIMITIVE(op,t,[||]),stack)
+ | Declarations.OpaqueDef _ | Declarations.Undef _ ->
if get_debug_cbv () then Feedback.msg_debug Pp.(str "Not unfolding " ++ debug_pr_key normt);
- (VAL(0,make_constr_ref k normt),stack)
+ (VAL(0,make_constr_ref k normt t),stack)
else
begin
if get_debug_cbv () then Feedback.msg_debug Pp.(str "Not unfolding " ++ debug_pr_key normt);
- (VAL(0,make_constr_ref k normt),stack)
+ (VAL(0,make_constr_ref k normt t),stack)
end
(* cbv_stack_term performs weak reduction on constr t under the subs
@@ -392,32 +459,58 @@ and cbv_stack_value info env = function
| (COFIXP(cofix,env,[||]), APP(appl,TOP)) -> COFIXP(cofix,env,appl)
| (CONSTR(c,[||]), APP(appl,TOP)) -> CONSTR(c,appl)
+ (* primitive apply to arguments *)
+ | (PRIMITIVE(op,c,[||]), APP(appl,stk)) ->
+ let nargs = CPrimitives.arity op in
+ let len = Array.length appl in
+ if nargs <= len then
+ let args =
+ if len = nargs then appl
+ else Array.sub appl 0 nargs in
+ let stk =
+ if nargs < len then
+ stack_app (Array.sub appl nargs (len - nargs)) stk
+ else stk in
+ match VredNative.red_prim info.env () op args with
+ | Some (CONSTR (c, args)) ->
+ (* args must be moved to the stack to allow future reductions *)
+ cbv_stack_value info env (CONSTR(c, [||]), stack_app args stk)
+ | Some v -> cbv_stack_value info env (v,stk)
+ | None -> mkSTACK(PRIMITIVE(op,c,args), stk)
+ else (* partical application *)
+ (assert (stk = TOP);
+ PRIMITIVE(op,c,appl))
+
(* definitely a value *)
| (head,stk) -> mkSTACK(head, stk)
-and cbv_value_cache info ref = match KeyTable.find info.tab ref with
-| v -> Some v
-| exception Not_found ->
- try
- let body = match ref with
- | RelKey n ->
- let open Context.Rel.Declaration in
- begin match Environ.lookup_rel n info.env with
- | LocalDef (_, c, _) -> lift n c
- | LocalAssum _ -> raise Not_found
- end
- | VarKey id ->
- let open Context.Named.Declaration in
- begin match Environ.lookup_named id info.env with
- | LocalDef (_, c, _) -> c
- | LocalAssum _ -> raise Not_found
- end
- | ConstKey cst -> Environ.constant_value_in info.env cst
+and cbv_value_cache info ref =
+ try KeyTable.find info.tab ref with
+ Not_found ->
+ let v =
+ try
+ let body = match ref with
+ | RelKey n ->
+ let open Context.Rel.Declaration in
+ begin match Environ.lookup_rel n info.env with
+ | LocalDef (_, c, _) -> lift n c
+ | LocalAssum _ -> raise Not_found
+ end
+ | VarKey id ->
+ let open Context.Named.Declaration in
+ begin match Environ.lookup_named id info.env with
+ | LocalDef (_, c, _) -> c
+ | LocalAssum _ -> raise Not_found
+ end
+ | ConstKey cst -> Environ.constant_value_in info.env cst
+ in
+ let v = cbv_stack_term info TOP (subs_id 0) body in
+ Declarations.Def v
+ with
+ | Environ.NotEvaluableConst (Environ.IsPrimitive op) -> Declarations.Primitive op
+ | Not_found | Environ.NotEvaluableConst _ -> Declarations.Undef None
in
- let v = cbv_stack_term info TOP (subs_id 0) body in
- let () = KeyTable.add info.tab ref v in
- Some v
- with Not_found | Environ.NotEvaluableConst _ -> None
+ KeyTable.add info.tab ref v; v
(* When we are sure t will never produce a redex with its stack, we
* normalize (even under binders) the applied terms and we build the
@@ -471,6 +564,8 @@ and cbv_norm_value info = function (* reduction under binders *)
Array.map (cbv_norm_value info) args)
| CONSTR (c,args) ->
mkApp(mkConstructU c, Array.map (cbv_norm_value info) args)
+ | PRIMITIVE(op,c,args) ->
+ mkApp(c,Array.map (cbv_norm_value info) args)
(* with profiling *)
let cbv_norm infos constr =
diff --git a/pretyping/cbv.mli b/pretyping/cbv.mli
index 83844c95a7..0a1e771921 100644
--- a/pretyping/cbv.mli
+++ b/pretyping/cbv.mli
@@ -36,6 +36,7 @@ type cbv_value =
| FIXP of fixpoint * cbv_value subs * cbv_value array
| COFIXP of cofixpoint * cbv_value subs * cbv_value array
| CONSTR of constructor Univ.puniverses * cbv_value array
+ | PRIMITIVE of CPrimitives.t * Constr.t * cbv_value array
and cbv_stack =
| TOP
diff --git a/pretyping/constr_matching.ml b/pretyping/constr_matching.ml
index 032e4bbf85..94257fedd7 100644
--- a/pretyping/constr_matching.ml
+++ b/pretyping/constr_matching.ml
@@ -410,9 +410,10 @@ let matches_core env sigma allow_bound_rels
| PEvar (c1,args1), Evar (c2,args2) when Evar.equal c1 c2 ->
Array.fold_left2 (sorec ctx env) subst args1 args2
+ | PInt i1, Int i2 when Uint63.equal i1 i2 -> subst
| (PRef _ | PVar _ | PRel _ | PApp _ | PProj _ | PLambda _
| PProd _ | PLetIn _ | PSort _ | PIf _ | PCase _
- | PFix _ | PCoFix _| PEvar _), _ -> raise PatternMatchingFailure
+ | PFix _ | PCoFix _| PEvar _ | PInt _), _ -> raise PatternMatchingFailure
in
sorec [] env ((Id.Map.empty,Id.Set.empty), Id.Map.empty) pat c
@@ -530,7 +531,7 @@ let sub_match ?(closed=true) env sigma pat c =
aux env term mk_ctx next
with Retyping.RetypeError _ -> next ()
end
- | Construct _| Ind _|Evar _|Const _ | Rel _|Meta _|Var _|Sort _ ->
+ | Construct _| Ind _|Evar _|Const _ | Rel _|Meta _|Var _|Sort _ | Int _ ->
next ()
in
here next
diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml
index 517834f014..6746e4b902 100644
--- a/pretyping/detyping.ml
+++ b/pretyping/detyping.ml
@@ -739,7 +739,7 @@ and detype_r d flags avoid env sigma t =
let id,l =
try
let id = match Evd.evar_ident evk sigma with
- | None -> Termops.pr_evar_suggested_name evk sigma
+ | None -> Termops.evar_suggested_name evk sigma
| Some id -> id
in
let l = Evd.evar_instance_array bound_to_itself_or_letin (Evd.find sigma evk) cl in
@@ -766,6 +766,7 @@ and detype_r d flags avoid env sigma t =
p c bl
| Fix (nvn,recdef) -> detype_fix (detype d flags) avoid env sigma nvn recdef
| CoFix (n,recdef) -> detype_cofix (detype d flags) avoid env sigma n recdef
+ | Int i -> GInt i
and detype_eqns d flags avoid env sigma ci computable constructs consnargsl bl =
try
@@ -959,6 +960,7 @@ let rec subst_glob_constr subst = DAst.map (function
| GSort _
| GVar _
| GEvar _
+ | GInt _
| GPatVar _ as raw -> raw
| GApp (r,rl) as raw ->
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml
index ed28cc7725..aa30ed8d2e 100644
--- a/pretyping/evarconv.ml
+++ b/pretyping/evarconv.ml
@@ -107,7 +107,7 @@ let flex_kind_of_term ts env evd c sk =
Option.cata (fun x -> MaybeFlexible x) Rigid (eval_flexible_term ts env evd c)
| Lambda _ when not (Option.is_empty (Stack.decomp sk)) -> MaybeFlexible c
| Evar ev -> Flexible ev
- | Lambda _ | Prod _ | Sort _ | Ind _ | Construct _ | CoFix _ -> Rigid
+ | Lambda _ | Prod _ | Sort _ | Ind _ | Construct _ | CoFix _ | Int _ -> Rigid
| Meta _ -> Rigid
| Fix _ -> Rigid (* happens when the fixpoint is partially applied *)
| Cast _ | App _ | Case _ -> assert false
@@ -127,7 +127,7 @@ let occur_rigidly (evk,_ as ev) evd t =
let rec aux t =
match EConstr.kind evd t with
| App (f, c) -> if aux f then Array.exists aux c else false
- | Construct _ | Ind _ | Sort _ | Meta _ | Fix _ | CoFix _ -> true
+ | Construct _ | Ind _ | Sort _ | Meta _ | Fix _ | CoFix _ | Int _ -> true
| Proj (p, c) -> not (aux c)
| Evar (evk',_) -> if Evar.equal evk evk' then raise Occur else false
| Cast (p, _, _) -> aux p
@@ -769,7 +769,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) ts env evd pbty
only if necessary) or the second argument is potentially
usable as a canonical projection or canonical value *)
let rec is_unnamed (hd, args) = match EConstr.kind i hd with
- | (Var _|Construct _|Ind _|Const _|Prod _|Sort _) ->
+ | (Var _|Construct _|Ind _|Const _|Prod _|Sort _|Int _) ->
Stack.not_purely_applicative args
| (CoFix _|Meta _|Rel _)-> true
| Evar _ -> Stack.not_purely_applicative args
@@ -887,8 +887,9 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) ts env evd pbty
| Const _, Const _
| Ind _, Ind _
- | Construct _, Construct _ ->
- rigids env evd sk1 term1 sk2 term2
+ | Construct _, Construct _
+ | Int _, Int _ ->
+ rigids env evd sk1 term1 sk2 term2
| Construct u, _ ->
eta_constructor ts env evd sk1 u sk2 term2
@@ -923,9 +924,7 @@ and evar_eqappr_x ?(rhs_is_already_stuck = false) ts env evd pbty
|Some (sk1',sk2'), Success i' -> evar_conv_x ts env i' CONV (Stack.zip i' (term1,sk1')) (Stack.zip i' (term2,sk2'))
end
- | (Ind _ | Sort _ | Prod _ | CoFix _ | Fix _ | Rel _ | Var _ | Const _), _ ->
- UnifFailure (evd,NotSameHead)
- | _, (Ind _ | Sort _ | Prod _ | CoFix _ | Fix _ | Rel _ | Var _ | Const _) ->
+ | (Ind _ | Sort _ | Prod _ | CoFix _ | Fix _ | Rel _ | Var _ | Const _ | Int _), _ ->
UnifFailure (evd,NotSameHead)
| (App _ | Cast _ | Case _ | Proj _), _ -> assert false
diff --git a/pretyping/glob_ops.ml b/pretyping/glob_ops.ml
index e14766f370..6b61b1452e 100644
--- a/pretyping/glob_ops.ml
+++ b/pretyping/glob_ops.ml
@@ -152,8 +152,10 @@ let mk_glob_constr_eq f c1 c2 = match DAst.get c1, DAst.get c2 with
Namegen.intro_pattern_naming_eq nam1 nam2
| GCast (c1, t1), GCast (c2, t2) ->
f c1 c2 && cast_type_eq f t1 t2
+ | GInt i1, GInt i2 -> Uint63.equal i1 i2
| (GRef _ | GVar _ | GEvar _ | GPatVar _ | GApp _ | GLambda _ | GProd _ | GLetIn _ |
- GCases _ | GLetTuple _ | GIf _ | GRec _ | GSort _ | GHole _ | GCast _ ), _ -> false
+ GCases _ | GLetTuple _ | GIf _ | GRec _ | GSort _ | GHole _ | GCast _ |
+ GInt _), _ -> false
let rec glob_constr_eq c = mk_glob_constr_eq glob_constr_eq c
@@ -214,7 +216,7 @@ let map_glob_constr_left_to_right f = DAst.map (function
let comp1 = f c in
let comp2 = map_cast_type f k in
GCast (comp1,comp2)
- | (GVar _ | GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) as x -> x
+ | (GVar _ | GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _ | GInt _) as x -> x
)
let map_glob_constr = map_glob_constr_left_to_right
@@ -246,9 +248,8 @@ let fold_glob_constr f acc = DAst.with_val (function
let acc = match k with
| CastConv t | CastVM t | CastNative t -> f acc t | CastCoerce -> acc in
f acc c
- | (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) -> acc
+ | (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _ | GInt _) -> acc
)
-
let fold_return_type_with_binders f g v acc (na,tyopt) =
Option.fold_left (f (Name.fold_right g na v)) acc tyopt
@@ -289,7 +290,7 @@ let fold_glob_constr_with_binders g f v acc = DAst.(with_val (function
let acc = match k with
| CastConv t | CastVM t | CastNative t -> f v acc t | CastCoerce -> acc in
f v acc c
- | (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _) -> acc))
+ | (GSort _ | GHole _ | GRef _ | GEvar _ | GPatVar _ | GInt _) -> acc))
let iter_glob_constr f = fold_glob_constr (fun () -> f) ()
diff --git a/pretyping/glob_term.ml b/pretyping/glob_term.ml
index c405fcfc72..8670c1d964 100644
--- a/pretyping/glob_term.ml
+++ b/pretyping/glob_term.ml
@@ -82,6 +82,7 @@ type 'a glob_constr_r =
| GSort of glob_sort
| GHole of Evar_kinds.t * Namegen.intro_pattern_naming_expr * Genarg.glob_generic_argument option
| GCast of 'a glob_constr_g * 'a glob_constr_g cast_type
+ | GInt of Uint63.t
and 'a glob_constr_g = ('a glob_constr_r, 'a) DAst.t
and 'a glob_decl_g = Name.t * binding_kind * 'a glob_constr_g option * 'a glob_constr_g
diff --git a/pretyping/heads.ml b/pretyping/heads.ml
index ccbb2934bc..cdeec875a2 100644
--- a/pretyping/heads.ml
+++ b/pretyping/heads.ml
@@ -91,6 +91,7 @@ let kind_of_head env t =
| Proj (p,c) -> RigidHead RigidOther
| Case (_,_,c,_) -> aux k [] c true
+ | Int _ -> ConstructorHead
| Fix ((i,j),_) ->
let n = i.(j) in
try aux k [] (List.nth l n) true
diff --git a/pretyping/inferCumulativity.ml b/pretyping/inferCumulativity.ml
index e46d03b743..b5a6ba6be5 100644
--- a/pretyping/inferCumulativity.ml
+++ b/pretyping/inferCumulativity.ml
@@ -100,6 +100,7 @@ let rec infer_fterm cv_pb infos variances hd stk =
let variances = infer_stack infos variances stk in
infer_vect infos variances (Array.map (mk_clos e) args)
| FRel _ -> infer_stack infos variances stk
+ | FInt _ -> infer_stack infos variances stk
| FFlex fl ->
let variances = infer_table_key infos variances fl in
infer_stack infos variances stk
@@ -155,6 +156,10 @@ and infer_stack infos variances (stk:CClosure.stack) =
infer_vect infos variances (Array.map (mk_clos e) br)
| Zshift _ -> variances
| Zupdate _ -> variances
+ | Zprimitive (_,_,rargs,kargs) ->
+ let variances = List.fold_left (fun variances c -> infer_fterm CONV infos variances c []) variances rargs in
+ let variances = List.fold_left (fun variances (_,c) -> infer_fterm CONV infos variances c []) variances kargs in
+ variances
in
infer_stack infos variances stk
diff --git a/pretyping/nativenorm.ml b/pretyping/nativenorm.ml
index dc2663c1ca..b7090e69da 100644
--- a/pretyping/nativenorm.ml
+++ b/pretyping/nativenorm.ml
@@ -120,13 +120,6 @@ let construct_of_constr_notnative const env tag (mind, _ as ind) u allargs =
let mib,mip = lookup_mind_specif env ind in
let nparams = mib.mind_nparams in
let params = Array.sub allargs 0 nparams in
- try
- if const then
- let ctyp = type_constructor mind mib u (mip.mind_nf_lc.(0)) params in
- Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (GlobRef.IndRef ind) tag, ctyp
- else
- raise Not_found
- with Not_found ->
let i = invert_tag const tag mip.mind_reloc_tbl in
let ctyp = type_constructor mind mib u (mip.mind_nf_lc.(i-1)) params in
(mkApp(mkConstructU((ind,i),u), params), ctyp)
@@ -137,7 +130,9 @@ let construct_of_constr const env sigma tag typ =
match EConstr.kind_upto sigma t with
| Ind (ind,u) ->
construct_of_constr_notnative const env tag ind u l
- | _ -> assert false
+ | _ ->
+ assert (Constr.equal t (Typeops.type_of_int env));
+ (mkInt (Uint63.of_int tag), t)
let construct_of_constr_const env sigma tag typ =
fst (construct_of_constr true env sigma tag typ)
@@ -208,6 +203,7 @@ let rec nf_val env sigma v typ =
let body = nf_val env sigma (f (mk_rel_accu lvl)) codom in
mkLambda(name,dom,body)
| Vconst n -> construct_of_constr_const env sigma n typ
+ | Vint64 i -> i |> Uint63.of_int64 |> mkInt
| Vblock b ->
let capp,ctyp = construct_of_constr_block env sigma (block_tag b) typ in
let args = nf_bargs env sigma b ctyp in
diff --git a/pretyping/pattern.ml b/pretyping/pattern.ml
index be7ebe49cf..2ca7f21e8d 100644
--- a/pretyping/pattern.ml
+++ b/pretyping/pattern.ml
@@ -39,6 +39,7 @@ type constr_pattern =
(int * bool list * constr_pattern) list (** index of constructor, nb of args *)
| PFix of (int array * int) * (Name.t array * constr_pattern array * constr_pattern array)
| PCoFix of int * (Name.t array * constr_pattern array * constr_pattern array)
+ | PInt of Uint63.t
(** Nota : in a [PCase], the array of branches might be shorter than
expected, denoting the use of a final "_ => _" branch *)
diff --git a/pretyping/patternops.ml b/pretyping/patternops.ml
index 248d5d0a0e..6803ea7d9b 100644
--- a/pretyping/patternops.ml
+++ b/pretyping/patternops.ml
@@ -61,9 +61,11 @@ let rec constr_pattern_eq p1 p2 = match p1, p2 with
Int.equal i1 i2 && rec_declaration_eq f1 f2
| PProj (p1, t1), PProj (p2, t2) ->
Projection.equal p1 p2 && constr_pattern_eq t1 t2
+| PInt i1, PInt i2 ->
+ Uint63.equal i1 i2
| (PRef _ | PVar _ | PEvar _ | PRel _ | PApp _ | PSoApp _
| PLambda _ | PProd _ | PLetIn _ | PSort _ | PMeta _
- | PIf _ | PCase _ | PFix _ | PCoFix _ | PProj _), _ -> false
+ | PIf _ | PCase _ | PFix _ | PCoFix _ | PProj _ | PInt _), _ -> false
(** FIXME: fixpoint and cofixpoint should be relativized to pattern *)
and pattern_eq (i1, j1, p1) (i2, j2, p2) =
@@ -90,7 +92,8 @@ let rec occur_meta_pattern = function
(occur_meta_pattern c) ||
(List.exists (fun (_,_,p) -> occur_meta_pattern p) br)
| PMeta _ | PSoApp _ -> true
- | PEvar _ | PVar _ | PRef _ | PRel _ | PSort _ | PFix _ | PCoFix _ -> false
+ | PEvar _ | PVar _ | PRef _ | PRel _ | PSort _ | PFix _ | PCoFix _
+ | PInt _ -> false
let rec occurn_pattern n = function
| PRel p -> Int.equal n p
@@ -111,7 +114,7 @@ let rec occurn_pattern n = function
(List.exists (fun (_,_,p) -> occurn_pattern n p) br)
| PMeta _ | PSoApp _ -> true
| PEvar (_,args) -> Array.exists (occurn_pattern n) args
- | PVar _ | PRef _ | PSort _ -> false
+ | PVar _ | PRef _ | PSort _ | PInt _ -> false
| PFix (_,(_,tl,bl)) ->
Array.exists (occurn_pattern n) tl || Array.exists (occurn_pattern (n+Array.length tl)) bl
| PCoFix (_,(_,tl,bl)) ->
@@ -134,7 +137,7 @@ let rec head_pattern_bound t =
-> raise BoundPattern
(* Perhaps they were arguments, but we don't beta-reduce *)
| PLambda _ -> raise BoundPattern
- | PCoFix _ -> anomaly ~label:"head_pattern_bound" (Pp.str "not a type.")
+ | PCoFix _ | PInt _ -> anomaly ~label:"head_pattern_bound" (Pp.str "not a type.")
let head_of_constr_reference sigma c = match EConstr.kind sigma c with
| Const (sp,_) -> ConstRef sp
@@ -209,7 +212,8 @@ let pattern_of_constr env sigma t =
let push env na2 c2 = push_rel (LocalAssum (na2,c2)) env in
let env' = Array.fold_left2 push env lna tl in
PCoFix (ln,(lna,Array.map (pattern_of_constr env) tl,
- Array.map (pattern_of_constr env') bl)) in
+ Array.map (pattern_of_constr env') bl))
+ | Int i -> PInt i in
pattern_of_constr env t
(* To process patterns, we need a translation without typing at all. *)
@@ -231,7 +235,7 @@ let map_pattern_with_binders g f l = function
let l' = Array.fold_left (fun l na -> g na l) l lna in
PCoFix (ln,(lna,Array.map (f l) tl,Array.map (f l') bl))
(* Non recursive *)
- | (PVar _ | PEvar _ | PRel _ | PRef _ | PSort _ | PMeta _ as x) -> x
+ | (PVar _ | PEvar _ | PRel _ | PRef _ | PSort _ | PMeta _ | PInt _ as x) -> x
let error_instantiate_pattern id l =
let is = match l with
@@ -287,7 +291,8 @@ let rec subst_pattern subst pat =
pattern_of_constr env evd t.Univ.univ_abstracted_value)
| PVar _
| PEvar _
- | PRel _ -> pat
+ | PRel _
+ | PInt _ -> pat
| PProj (p,c) ->
let p' = Projection.map (subst_mind subst) p in
let c' = subst_pattern subst c in
@@ -488,6 +493,7 @@ let rec pat_of_raw metas vars = DAst.with_loc_val (fun ?loc -> function
let names = Array.map (fun id -> Name id) ids in
PCoFix (n, (names, tl, cl))
+ | GInt i -> PInt i
| GPatVar _ | GIf _ | GLetTuple _ | GCases _ | GEvar _ ->
err ?loc (Pp.str "Non supported pattern."))
diff --git a/pretyping/pretype_errors.ml b/pretyping/pretype_errors.ml
index 01b0d96f98..dc6607557d 100644
--- a/pretyping/pretype_errors.ml
+++ b/pretyping/pretype_errors.ml
@@ -53,6 +53,7 @@ type pretype_error =
| NonLinearUnification of Name.t * constr
(* Pretyping *)
| VarNotFound of Id.t
+ | EvarNotFound of Id.t
| UnexpectedType of constr * constr
| NotProduct of constr
| TypingError of type_error
@@ -167,6 +168,9 @@ let error_not_product ?loc env sigma c =
let error_var_not_found ?loc env sigma s =
raise_pretype_error ?loc (env, sigma, VarNotFound s)
+let error_evar_not_found ?loc env sigma id =
+ raise_pretype_error ?loc (env, sigma, EvarNotFound id)
+
(*s Typeclass errors *)
let unsatisfiable_constraints env evd ev comp =
diff --git a/pretyping/pretype_errors.mli b/pretyping/pretype_errors.mli
index 51103ca194..a0d459fe6b 100644
--- a/pretyping/pretype_errors.mli
+++ b/pretyping/pretype_errors.mli
@@ -59,6 +59,7 @@ type pretype_error =
| NonLinearUnification of Name.t * constr
(** Pretyping *)
| VarNotFound of Id.t
+ | EvarNotFound of Id.t
| UnexpectedType of constr * constr
| NotProduct of constr
| TypingError of type_error
@@ -155,6 +156,8 @@ val error_not_product :
val error_var_not_found : ?loc:Loc.t -> env -> Evd.evar_map -> Id.t -> 'b
+val error_evar_not_found : ?loc:Loc.t -> env -> Evd.evar_map -> Id.t -> 'b
+
(** {6 Typeclass errors } *)
val unsatisfiable_constraints : env -> Evd.evar_map -> Evar.t option ->
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index ace2868255..57705fa209 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -486,8 +486,7 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : GlobEnv.t) (sigma
let id = interp_ltac_id env id in
let evk =
try Evd.evar_key id sigma
- with Not_found ->
- user_err ?loc (str "Unknown existential variable.") in
+ with Not_found -> error_evar_not_found ?loc !!env sigma id in
let hyps = evar_filtered_context (Evd.find sigma evk) in
let sigma, args = pretype_instance k0 resolve_tc env sigma loc hyps evk inst in
let c = mkEvar (evk, args) in
@@ -954,6 +953,14 @@ let rec pretype k0 resolve_tc (tycon : type_constraint) (env : GlobEnv.t) (sigma
sigma, { uj_val = v; uj_type = tval }
in inh_conv_coerce_to_tycon ?loc env sigma cj tycon
+ | GInt i ->
+ let resj =
+ try Typing.judge_of_int !!env i
+ with Invalid_argument _ ->
+ user_err ?loc ~hdr:"pretype" (str "Type of int63 should be registered first.")
+ in
+ inh_conv_coerce_to_tycon ?loc env sigma resj tycon
+
and pretype_instance k0 resolve_tc env sigma loc hyps evk update =
let f decl (subst,update,sigma) =
let id = NamedDecl.get_id decl in
diff --git a/pretyping/reductionops.ml b/pretyping/reductionops.ml
index 9c9877fd23..98ca329117 100644
--- a/pretyping/reductionops.ml
+++ b/pretyping/reductionops.ml
@@ -279,7 +279,9 @@ sig
| Case of case_info * 'a * 'a array * Cst_stack.t
| Proj of Projection.t * Cst_stack.t
| Fix of ('a, 'a) pfixpoint * 'a t * Cst_stack.t
+ | Primitive of CPrimitives.t * (Constant.t * EInstance.t) * 'a t * CPrimitives.args_red * Cst_stack.t
| Cst of cst_member * int * int list * 'a t * Cst_stack.t
+
and 'a t = 'a member list
exception IncompatibleFold2
@@ -308,6 +310,8 @@ sig
val nth : 'a t -> int -> 'a
val best_state : evar_map -> constr * constr t -> Cst_stack.t -> constr * constr t
val zip : ?refold:bool -> evar_map -> constr * constr t -> constr
+ val check_native_args : CPrimitives.t -> 'a t -> bool
+ val get_next_primitive_args : CPrimitives.args_red -> 'a t -> CPrimitives.args_red * ('a t * 'a * 'a t) option
end =
struct
open EConstr
@@ -336,7 +340,9 @@ struct
| Case of case_info * 'a * 'a array * Cst_stack.t
| Proj of Projection.t * Cst_stack.t
| Fix of ('a, 'a) pfixpoint * 'a t * Cst_stack.t
+ | Primitive of CPrimitives.t * (Constant.t * EInstance.t) * 'a t * CPrimitives.args_red * Cst_stack.t
| Cst of cst_member * int * int list * 'a t * Cst_stack.t
+
and 'a t = 'a member list
(* Debugging printer *)
@@ -354,6 +360,9 @@ struct
| Fix (f,args,cst) ->
str "ZFix(" ++ Constr.debug_print_fix pr_c f
++ pr_comma () ++ pr pr_c args ++ str ")"
+ | Primitive (p,c,args,kargs,cst_l) ->
+ str "ZPrimitive(" ++ str (CPrimitives.to_string p)
+ ++ pr_comma () ++ pr pr_c args ++ str ")"
| Cst (mem,curr,remains,params,cst_l) ->
str "ZCst(" ++ pr_cst_member pr_c mem ++ pr_comma () ++ int curr
++ pr_comma () ++
@@ -420,7 +429,7 @@ struct
equal_cst_member c1 c2
&& equal_rec (List.rev params1) (List.rev params2)
&& equal_rec s1' s2'
- | ((App _|Case _|Proj _|Fix _|Cst _)::_|[]), _ -> false
+ | ((App _|Case _|Proj _|Fix _|Cst _|Primitive _)::_|[]), _ -> false
in equal_rec (List.rev sk1) (List.rev sk2)
let compare_shape stk1 stk2 =
@@ -435,9 +444,11 @@ struct
Int.equal bal 0 && compare_rec 0 s1 s2
| (Fix(_,a1,_)::s1, Fix(_,a2,_)::s2) ->
Int.equal bal 0 && compare_rec 0 a1 a2 && compare_rec 0 s1 s2
+ | (Primitive(_,_,a1,_,_)::s1, Primitive(_,_,a2,_,_)::s2) ->
+ Int.equal bal 0 && compare_rec 0 a1 a2 && compare_rec 0 s1 s2
| (Cst (_,_,_,p1,_)::s1, Cst (_,_,_,p2,_)::s2) ->
- Int.equal bal 0 && compare_rec 0 p1 p2 && compare_rec 0 s1 s2
- | (_,_) -> false in
+ Int.equal bal 0 && compare_rec 0 p1 p2 && compare_rec 0 s1 s2
+ | ((Case _|Proj _|Fix _|Cst _|Primitive _) :: _ | []) ,_ -> false in
compare_rec 0 stk1 stk2
exception IncompatibleFold2
@@ -459,7 +470,7 @@ struct
| Cst (cst1,_,_,params1,_) :: q1, Cst (cst2,_,_,params2,_) :: q2 ->
let o' = aux o (List.rev params1) (List.rev params2) in
aux o' q1 q2
- | (((App _|Case _|Proj _|Fix _| Cst _) :: _|[]), _) ->
+ | (((App _|Case _|Proj _|Fix _|Cst _|Primitive _) :: _|[]), _) ->
raise IncompatibleFold2
in aux o (List.rev sk1) (List.rev sk2)
@@ -473,7 +484,9 @@ struct
Fix ((r,(na,Array.map f ty, Array.map f bo)),map f arg,alt)
| Cst (cst,curr,remains,params,alt) ->
Cst (cst,curr,remains,map f params,alt)
- ) x
+ | Primitive (p,c,args,kargs,cst_l) ->
+ Primitive(p,c, map f args, kargs, cst_l)
+ ) x
let append_app_list l s =
let a = Array.of_list l in
@@ -481,7 +494,7 @@ struct
let rec args_size = function
| App (i,_,j)::s -> j + 1 - i + args_size s
- | (Case _|Fix _|Proj _|Cst _)::_ | [] -> 0
+ | (Case _|Fix _|Proj _|Cst _|Primitive _)::_ | [] -> 0
let strip_app s =
let rec aux out = function
@@ -504,7 +517,8 @@ struct
in aux n [] s
let not_purely_applicative args =
- List.exists (function (Fix _ | Case _ | Proj _ | Cst _) -> true | _ -> false) args
+ List.exists (function (Fix _ | Case _ | Proj _ | Cst _) -> true
+ | App _ | Primitive _ -> false) args
let will_expose_iota args =
List.exists
(function (Fix (_,_,l) | Case (_,_,_,l) |
@@ -588,9 +602,26 @@ struct
| f, (Proj (p,cst_l)::s) when refold ->
zip (best_state sigma (mkProj (p,f),s) cst_l)
| f, (Proj (p,_)::s) -> zip (mkProj (p,f),s)
+ | f, (Primitive (p,c,args,kargs,cst_l)::s) ->
+ zip (mkConstU c, args @ append_app [|f|] s)
in
zip s
+ (* Check if there is enough arguments on [stk] w.r.t. arity of [op] *)
+ let check_native_args op stk =
+ let nargs = CPrimitives.arity op in
+ let rargs = args_size stk in
+ nargs <= rargs
+
+ let get_next_primitive_args kargs stk =
+ let rec nargs = function
+ | [] -> 0
+ | CPrimitives.Kwhnf :: _ -> 0
+ | _ :: s -> 1 + nargs s
+ in
+ let n = nargs kargs in
+ (List.skipn (n+1) kargs, strip_n_app n stk)
+
end
(** The type of (machine) states (= lambda-bar-calculus' cuts) *)
@@ -815,6 +846,57 @@ let fix_recarg ((recindices,bodynum),_) stack =
with Not_found ->
None
+open Primred
+
+module CNativeEntries =
+struct
+
+ type elem = EConstr.t
+ type args = EConstr.t array
+ type evd = evar_map
+
+ let get = Array.get
+
+ let get_int evd e =
+ match EConstr.kind evd e with
+ | Int i -> i
+ | _ -> raise Primred.NativeDestKO
+
+ let mkInt env i =
+ mkInt i
+
+ let mkBool env b =
+ let (ct,cf) = get_bool_constructors env in
+ mkConstruct (if b then ct else cf)
+
+ let mkCarry env b e =
+ let int_ty = mkConst @@ get_int_type env in
+ let (c0,c1) = get_carry_constructors env in
+ mkApp (mkConstruct (if b then c1 else c0),[|int_ty;e|])
+
+ let mkIntPair env e1 e2 =
+ let int_ty = mkConst @@ get_int_type env in
+ let c = get_pair_constructor env in
+ mkApp(mkConstruct c, [|int_ty;int_ty;e1;e2|])
+
+ let mkLt env =
+ let (_eq, lt, _gt) = get_cmp_constructors env in
+ mkConstruct lt
+
+ let mkEq env =
+ let (eq, _lt, _gt) = get_cmp_constructors env in
+ mkConstruct eq
+
+ let mkGt env =
+ let (_eq, _lt, gt) = get_cmp_constructors env in
+ mkConstruct gt
+
+end
+
+module CredNative = RedNative(CNativeEntries)
+
+
+
(** Generic reduction function with environment
Here is where unfolded constant are stored in order to be
@@ -881,47 +963,55 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
(lazy (EConstr.to_constr sigma (Stack.zip sigma (x,stack))));
if CClosure.RedFlags.red_set flags (CClosure.RedFlags.fCONST c) then
let u' = EInstance.kind sigma u in
- (match constant_opt_value_in env (c, u') with
- | None -> fold ()
- | Some body ->
+ match constant_value_in env (c, u') with
+ | body ->
+ begin
let body = EConstr.of_constr body in
- if not tactic_mode
- then whrec (if refold then Cst_stack.add_cst (mkConstU const) cst_l else cst_l)
- (body, stack)
- else (* Looks for ReductionBehaviour *)
- match ReductionBehaviour.get (Globnames.ConstRef c) with
- | None -> whrec (Cst_stack.add_cst (mkConstU const) cst_l) (body, stack)
- | Some (recargs, nargs, flags) ->
- if (List.mem `ReductionNeverUnfold flags
- || (nargs > 0 && Stack.args_size stack < nargs))
- then fold ()
- else (* maybe unfolds *)
- if List.mem `ReductionDontExposeCase flags then
- let app_sk,sk = Stack.strip_app stack in
- let (tm',sk'),cst_l' =
- whrec (Cst_stack.add_cst (mkConstU const) cst_l) (body, app_sk)
- in
- let rec is_case x = match EConstr.kind sigma x with
- | Lambda (_,_, x) | LetIn (_,_,_, x) | Cast (x, _,_) -> is_case x
- | App (hd, _) -> is_case hd
- | Case _ -> true
- | _ -> false in
- if equal_stacks sigma (x, app_sk) (tm', sk')
- || Stack.will_expose_iota sk'
- || is_case tm'
- then fold ()
- else whrec cst_l' (tm', sk' @ sk)
- else match recargs with
- |[] -> (* if nargs has been specified *)
- (* CAUTION : the constant is NEVER refold
- (even when it hides a (co)fix) *)
- whrec cst_l (body, stack)
- |curr::remains -> match Stack.strip_n_app curr stack with
- | None -> fold ()
- | Some (bef,arg,s') ->
- whrec Cst_stack.empty
- (arg,Stack.Cst(Stack.Cst_const (fst const, u'),curr,remains,bef,cst_l)::s')
- ) else fold ()
+ if not tactic_mode
+ then whrec (if refold then Cst_stack.add_cst (mkConstU const) cst_l else cst_l)
+ (body, stack)
+ else (* Looks for ReductionBehaviour *)
+ match ReductionBehaviour.get (Globnames.ConstRef c) with
+ | None -> whrec (Cst_stack.add_cst (mkConstU const) cst_l) (body, stack)
+ | Some (recargs, nargs, flags) ->
+ if (List.mem `ReductionNeverUnfold flags
+ || (nargs > 0 && Stack.args_size stack < nargs))
+ then fold ()
+ else (* maybe unfolds *)
+ if List.mem `ReductionDontExposeCase flags then
+ let app_sk,sk = Stack.strip_app stack in
+ let (tm',sk'),cst_l' =
+ whrec (Cst_stack.add_cst (mkConstU const) cst_l) (body, app_sk)
+ in
+ let rec is_case x = match EConstr.kind sigma x with
+ | Lambda (_,_, x) | LetIn (_,_,_, x) | Cast (x, _,_) -> is_case x
+ | App (hd, _) -> is_case hd
+ | Case _ -> true
+ | _ -> false in
+ if equal_stacks sigma (x, app_sk) (tm', sk')
+ || Stack.will_expose_iota sk'
+ || is_case tm'
+ then fold ()
+ else whrec cst_l' (tm', sk' @ sk)
+ else match recargs with
+ |[] -> (* if nargs has been specified *)
+ (* CAUTION : the constant is NEVER refold
+ (even when it hides a (co)fix) *)
+ whrec cst_l (body, stack)
+ |curr::remains -> match Stack.strip_n_app curr stack with
+ | None -> fold ()
+ | Some (bef,arg,s') ->
+ whrec Cst_stack.empty
+ (arg,Stack.Cst(Stack.Cst_const (fst const, u'),curr,remains,bef,cst_l)::s')
+ end
+ | exception NotEvaluableConst (IsPrimitive p) when Stack.check_native_args p stack ->
+ let kargs = CPrimitives.kind p in
+ let (kargs,o) = Stack.get_next_primitive_args kargs stack in
+ (* Should not fail thanks to [check_native_args] *)
+ let (before,a,after) = Option.get o in
+ whrec Cst_stack.empty (a,Stack.Primitive(p,const,before,kargs,cst_l)::after)
+ | exception NotEvaluableConst _ -> fold ()
+ else fold ()
| Proj (p, c) when CClosure.RedFlags.red_projection flags p ->
(let npars = Projection.npars p in
if not tactic_mode then
@@ -1049,6 +1139,30 @@ let rec whd_state_gen ?csts ~refold ~tactic_mode flags env sigma =
|_ -> fold ()
else fold ()
+ | Int i ->
+ begin match Stack.strip_app stack with
+ | (_, Stack.Primitive(p,kn,rargs,kargs,cst_l')::s) ->
+ let more_to_reduce = List.exists (fun k -> CPrimitives.Kwhnf = k) kargs in
+ if more_to_reduce then
+ let (kargs,o) = Stack.get_next_primitive_args kargs s in
+ (* Should not fail because Primitive is put on the stack only if fully applied *)
+ let (before,a,after) = Option.get o in
+ whrec Cst_stack.empty (a,Stack.Primitive(p,kn,rargs @ Stack.append_app [|x|] before,kargs,cst_l')::after)
+ else
+ let n = List.length kargs in
+ let (args,s) = Stack.strip_app s in
+ let (args,extra_args) =
+ try List.chop n args
+ with List.IndexOutOfRange -> (args,[]) (* FIXME probably useless *)
+ in
+ let args = Array.of_list (Option.get (Stack.list_of_app_stack (rargs @ Stack.append_app [|x|] args))) in
+ begin match CredNative.red_prim env sigma p args with
+ | Some t -> whrec cst_l' (t,s)
+ | None -> ((mkApp (mkConstU kn, args), s), cst_l)
+ end
+ | _ -> fold ()
+ end
+
| Rel _ | Var _ | LetIn _ | Proj _ -> fold ()
| Sort _ | Ind _ | Prod _ -> fold ()
in
@@ -1127,7 +1241,8 @@ let local_whd_state_gen flags sigma =
|_ -> s
else s
- | Rel _ | Var _ | Sort _ | Prod _ | LetIn _ | Const _ | Ind _ | Proj _ -> s
+ | Rel _ | Var _ | Sort _ | Prod _ | LetIn _ | Const _ | Ind _ | Proj _
+ | Int _ -> s
in
whrec
@@ -1577,7 +1692,7 @@ let whd_betaiota_deltazeta_for_iota_state ts env sigma csts s =
if isConstruct sigma t_o then
whrec Cst_stack.empty (Stack.nth stack_o (Projection.npars p + Projection.arg p), stack'')
else s,csts'
- |_, ((Stack.App _|Stack.Cst _) :: _|[]) -> s,csts'
+ |_, ((Stack.App _|Stack.Cst _|Stack.Primitive _) :: _|[]) -> s,csts'
in whrec csts s
let find_conclusion env sigma =
diff --git a/pretyping/reductionops.mli b/pretyping/reductionops.mli
index a1fd610676..fae0b23b83 100644
--- a/pretyping/reductionops.mli
+++ b/pretyping/reductionops.mli
@@ -77,6 +77,7 @@ module Stack : sig
| Case of case_info * 'a * 'a array * Cst_stack.t
| Proj of Projection.t * Cst_stack.t
| Fix of ('a, 'a) pfixpoint * 'a t * Cst_stack.t
+ | Primitive of CPrimitives.t * (Constant.t * EInstance.t) * 'a t * CPrimitives.args_red * Cst_stack.t
| Cst of cst_member
* int (* current foccussed arg *)
* int list (* remaining args *)
diff --git a/pretyping/retyping.ml b/pretyping/retyping.ml
index 62ad296ecb..a76a203e37 100644
--- a/pretyping/retyping.ml
+++ b/pretyping/retyping.ml
@@ -143,6 +143,7 @@ let retype ?(polyprop=true) sigma =
with Invalid_argument _ -> retype_error BadRecursiveType)
| Cast (c,_, t) -> t
| Sort _ | Prod _ -> mkSort (sort_of env cstr)
+ | Int _ -> EConstr.of_constr (Typeops.type_of_int env)
and sort_of env t =
match EConstr.kind sigma t with
diff --git a/pretyping/tacred.ml b/pretyping/tacred.ml
index 2e7176a6b3..2308a541fb 100644
--- a/pretyping/tacred.ml
+++ b/pretyping/tacred.ml
@@ -48,8 +48,8 @@ let error_not_evaluable r =
spc () ++ str "to an evaluable reference.")
let is_evaluable_const env cst =
- is_transparent env (ConstKey cst) &&
- evaluable_constant cst env
+ is_transparent env (ConstKey cst) &&
+ (evaluable_constant cst env || is_primitive env cst)
let is_evaluable_var env id =
is_transparent env (VarKey id) && evaluable_named id env
diff --git a/pretyping/typing.ml b/pretyping/typing.ml
index b5729d7574..e8d935fcbb 100644
--- a/pretyping/typing.ml
+++ b/pretyping/typing.ml
@@ -306,6 +306,9 @@ let type_of_constructor env sigma ((ind,_ as ctor),u) =
let sigma = Evd.add_constraints sigma csts in
sigma, (EConstr.of_constr (rename_type ty (Names.GlobRef.ConstructRef ctor)))
+let judge_of_int env v =
+ Termops.on_judgment EConstr.of_constr (judge_of_int env v)
+
(* cstr must be in n.f. w.r.t. evars and execute returns a judgement
where both the term and type are in n.f. *)
let rec execute env sigma cstr =
@@ -408,6 +411,9 @@ let rec execute env sigma cstr =
let sigma, tj = type_judgment env sigma tj in
judge_of_cast env sigma cj k tj
+ | Int i ->
+ sigma, judge_of_int env i
+
and execute_recdef env sigma (names,lar,vdef) =
let sigma, larj = execute_array env sigma lar in
let sigma, lara = Array.fold_left_map (assumption_of_judgment env) sigma larj in
diff --git a/pretyping/typing.mli b/pretyping/typing.mli
index 79f2941554..1ea16bbf34 100644
--- a/pretyping/typing.mli
+++ b/pretyping/typing.mli
@@ -55,3 +55,4 @@ val judge_of_abstraction : Environ.env -> Name.t ->
val judge_of_product : Environ.env -> Name.t ->
unsafe_type_judgment -> unsafe_type_judgment -> unsafe_judgment
val judge_of_projection : env -> evar_map -> Projection.t -> unsafe_judgment -> unsafe_judgment
+val judge_of_int : Environ.env -> Uint63.t -> unsafe_judgment
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index f0cd5c5f6a..e4d96da0a6 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -550,7 +550,7 @@ let is_rigid_head sigma flags t =
match EConstr.kind sigma t with
| Const (cst,u) -> not (TransparentState.is_transparent_constant flags.modulo_delta cst)
| Ind (i,u) -> true
- | Construct _ -> true
+ | Construct _ | Int _ -> true
| Fix _ | CoFix _ -> true
| Rel _ | Var _ | Meta _ | Evar _ | Sort _ | Cast (_, _, _) | Prod (_, _, _)
| Lambda (_, _, _) | LetIn (_, _, _, _) | App (_, _) | Case (_, _, _, _)
@@ -641,7 +641,7 @@ let rec is_neutral env sigma ts t =
| Evar _ | Meta _ -> true
| Case (_, p, c, cl) -> is_neutral env sigma ts c
| Proj (p, c) -> is_neutral env sigma ts c
- | Lambda _ | LetIn _ | Construct _ | CoFix _ -> false
+ | Lambda _ | LetIn _ | Construct _ | CoFix _ | Int _ -> false
| Sort _ | Cast (_, _, _) | Prod (_, _, _) | Ind _ -> false (* Really? *)
| Fix _ -> false (* This is an approximation *)
| App _ -> assert false
@@ -1799,7 +1799,7 @@ let w_unify_to_subterm env evd ?(flags=default_unify_flags ()) (op,cl) =
| Cast (_, _, _) (* Is this expected? *)
| Rel _ | Var _ | Meta _ | Evar _ | Sort _ | Const _ | Ind _
- | Construct _ -> user_err Pp.(str "Match_subterm")))
+ | Construct _ | Int _ -> user_err Pp.(str "Match_subterm")))
in
try matchrec cl
with ex when precatchable_exception ex ->
@@ -1868,7 +1868,7 @@ let w_unify_to_subterm_all env evd ?(flags=default_unify_flags ()) (op,cl) =
| Cast (_, _, _) -> fail "Match_subterm" (* Is this expected? *)
| Rel _ | Var _ | Meta _ | Evar _ | Sort _ | Const _ | Ind _
- | Construct _ -> fail "Match_subterm"))
+ | Construct _ | Int _ -> fail "Match_subterm"))
in
let res = matchrec cl [] in
diff --git a/pretyping/vnorm.ml b/pretyping/vnorm.ml
index 113aac25da..083661a64b 100644
--- a/pretyping/vnorm.ml
+++ b/pretyping/vnorm.ml
@@ -57,7 +57,7 @@ let find_rectype_a env c =
let (t, l) = decompose_appvect (whd_all env c) in
match kind t with
| Ind ind -> (ind, l)
- | _ -> assert false
+ | _ -> raise Not_found
(* Instantiate inductives and parameters in constructor type *)
@@ -75,25 +75,18 @@ let type_constructor mind mib u typ params =
let construct_of_constr const env tag typ =
- let ((mind,_ as ind), u) as indu, allargs = find_rectype_a env typ in
- (* spiwack : here be a branch for specific decompilation handled by retroknowledge *)
- try
- if const then
- ((Retroknowledge.get_vm_decompile_constant_info env.retroknowledge (GlobRef.IndRef ind) tag),
- typ) (*spiwack: this may need to be changed in case there are parameters in the
- type which may cause a constant value to have an arity.
- (type_constructor seems to be all about parameters actually)
- but it shouldn't really matter since constant values don't use
- their ctyp in the rest of the code.*)
- else
- raise Not_found (* No retroknowledge function (yet) for block decompilation *)
- with Not_found ->
+ let (t, allargs) = decompose_appvect (whd_all env typ) in
+ match Constr.kind t with
+ | Ind ((mind,_ as ind), u as indu) ->
let mib,mip = lookup_mind_specif env ind in
let nparams = mib.mind_nparams in
let i = invert_tag const tag mip.mind_reloc_tbl in
let params = Array.sub allargs 0 nparams in
let ctyp = type_constructor mind mib u (mip.mind_nf_lc.(i-1)) params in
- (mkApp(mkConstructUi(indu,i), params), ctyp)
+ (mkApp(mkConstructUi(indu,i), params), ctyp)
+ | _ ->
+ assert (Constr.equal t (Typeops.type_of_int env));
+ (mkInt (Uint63.of_int tag), t)
let construct_of_constr_const env tag typ =
fst (construct_of_constr true env tag typ)
@@ -169,6 +162,7 @@ and nf_whd env sigma whd typ =
let capp,ctyp = construct_of_constr_block env tag typ in
let args = nf_bargs env sigma b ofs ctyp in
mkApp(capp,args)
+ | Vint64 i -> i |> Uint63.of_int64 |> mkInt
| Vatom_stk(Aid idkey, stk) ->
constr_type_of_idkey env sigma idkey stk
| Vatom_stk(Aind ((mi,i) as ind), stk) ->
@@ -344,9 +338,9 @@ and nf_fun env sigma f typ =
let name,dom,codom =
try decompose_prod env typ
with DestKO ->
- (* 27/2/13: Turned this into an anomaly *)
CErrors.anomaly
- (Pp.strbrk "Returned a functional value in a type not recognized as a product type.")
+ Pp.(strbrk "Returned a functional value in type " ++
+ Termops.Internal.print_constr_env env sigma (EConstr.of_constr typ))
in
let body = nf_val (push_rel (LocalAssum (name,dom)) env) sigma vb codom in
mkLambda(name,dom,body)
diff --git a/printing/prettyp.ml b/printing/prettyp.ml
index c417ef8a66..e0403a9f97 100644
--- a/printing/prettyp.ml
+++ b/printing/prettyp.ml
@@ -193,7 +193,7 @@ let opacity env =
| ConstRef cst ->
let cb = Environ.lookup_constant cst env in
(match cb.const_body with
- | Undef _ -> None
+ | Undef _ | Primitive _ -> None
| OpaqueDef _ -> Some FullyOpaque
| Def _ -> Some
(TransparentMaybeOpacified
@@ -267,7 +267,6 @@ let print_name_infos ref =
print_ref true ref None; blankline]
else
[] in
- print_polymorphism ref @
print_type_in_type ref @
print_primitive ref @
type_info_for_implicit @
@@ -559,7 +558,7 @@ let print_constant with_values sep sp udecl =
let open Univ in
let otab = Global.opaque_tables () in
match cb.const_body with
- | Undef _ | Def _ -> cb.const_universes
+ | Undef _ | Def _ | Primitive _ -> cb.const_universes
| OpaqueDef o ->
let body_uctxs = Opaqueproof.force_constraints otab o in
match cb.const_universes with
@@ -725,7 +724,10 @@ let print_full_pure_context env sigma =
| Def c ->
str "Definition " ++ print_basename con ++ cut () ++
str " : " ++ pr_ltype_env env sigma typ ++ cut () ++ str " := " ++
- pr_lconstr_env env sigma (Mod_subst.force_constr c))
+ pr_lconstr_env env sigma (Mod_subst.force_constr c)
+ | Primitive _ ->
+ str "Primitive " ++
+ print_basename con ++ str " : " ++ cut () ++ pr_ltype_env env sigma typ)
++ str "." ++ fnl () ++ fnl ()
| "INDUCTIVE" ->
let mind = Global.mind_of_delta_kn kn in
@@ -838,6 +840,7 @@ let print_about_any ?loc env sigma k udecl =
Dumpglob.add_glob ?loc ref;
pr_infos_list
(print_ref false ref udecl :: blankline ::
+ print_polymorphism ref @
print_name_infos ref @
(if Pp.ismt rb then [] else [rb]) @
print_opacity ref @
diff --git a/printing/proof_diffs.ml b/printing/proof_diffs.ml
index c1ea067567..878e9f477b 100644
--- a/printing/proof_diffs.ml
+++ b/printing/proof_diffs.ml
@@ -546,7 +546,7 @@ let to_constr p =
module GoalMap = Evar.Map
-let goal_to_evar g sigma = Id.to_string (Termops.pr_evar_suggested_name g sigma)
+let goal_to_evar g sigma = Id.to_string (Termops.evar_suggested_name g sigma)
open Goal.Set
diff --git a/proofs/goal_select.ml b/proofs/goal_select.ml
index cef3fd3f5e..955d797227 100644
--- a/proofs/goal_select.ml
+++ b/proofs/goal_select.ml
@@ -45,7 +45,7 @@ let parse_goal_selector = function
| "!" -> SelectAlreadyFocused
| "all" -> SelectAll
| i ->
- let err_msg = "The default selector must be \"all\" or a natural number." in
+ let err_msg = "The default selector must be \"all\", \"!\" or a natural number." in
begin try
let i = int_of_string i in
if i < 0 then CErrors.user_err Pp.(str err_msg);
diff --git a/proofs/proof_global.ml b/proofs/proof_global.ml
index 4cc73f419e..9ee9e7ae2c 100644
--- a/proofs/proof_global.ml
+++ b/proofs/proof_global.ml
@@ -22,51 +22,6 @@ open Names
module NamedDecl = Context.Named.Declaration
-(*** Proof Modes ***)
-
-(* Type of proof modes :
- - A function [set] to set it *from standard mode*
- - A function [reset] to reset the *standard mode* from it *)
-type proof_mode_name = string
-type proof_mode = {
- name : proof_mode_name ;
- set : unit -> unit ;
- reset : unit -> unit
-}
-
-let proof_modes = Hashtbl.create 6
-let find_proof_mode n =
- try Hashtbl.find proof_modes n
- with Not_found ->
- CErrors.user_err Pp.(str (Format.sprintf "No proof mode named \"%s\"." n))
-
-let register_proof_mode ({name = n} as m) =
- Hashtbl.add proof_modes n (CEphemeron.create m)
-
-(* initial mode: standard mode *)
-let standard = { name = "No" ; set = (fun ()->()) ; reset = (fun () -> ()) }
-let _ = register_proof_mode standard
-
-(* Default proof mode, to be set at the beginning of proofs. *)
-let default_proof_mode = ref (find_proof_mode "No")
-
-let get_default_proof_mode_name () =
- (CEphemeron.default !default_proof_mode standard).name
-
-let proof_mode_opt_name = ["Default";"Proof";"Mode"]
-let () =
- Goptions.(declare_string_option {
- optdepr = false;
- optname = "default proof mode" ;
- optkey = proof_mode_opt_name ;
- optread = begin fun () ->
- (CEphemeron.default !default_proof_mode standard).name
- end;
- optwrite = begin fun n ->
- default_proof_mode := find_proof_mode n
- end
- })
-
(*** Proof Global Environment ***)
(* Extra info on proofs. *)
@@ -95,7 +50,6 @@ type pstate = {
endline_tactic : Genarg.glob_generic_argument option;
section_vars : Constr.named_context option;
proof : Proof.t;
- mode : proof_mode CEphemeron.key;
universe_decl: UState.universe_decl;
strength : Decl_kinds.goal_kind;
}
@@ -109,23 +63,8 @@ let apply_terminator f = f
to be resumed when the current proof is closed or aborted. *)
let pstates = ref ([] : pstate list)
-(* Current proof_mode, for bookkeeping *)
-let current_proof_mode = ref !default_proof_mode
-
-(* combinators for proof modes *)
-let update_proof_mode () =
- match !pstates with
- | { mode = m } :: _ ->
- CEphemeron.iter_opt !current_proof_mode (fun x -> x.reset ());
- current_proof_mode := m;
- CEphemeron.iter_opt !current_proof_mode (fun x -> x.set ())
- | _ ->
- CEphemeron.iter_opt !current_proof_mode (fun x -> x.reset ());
- current_proof_mode := find_proof_mode "No"
-
(* combinators for the current_proof lists *)
-let push a l = l := a::!l;
- update_proof_mode ()
+let push a l = l := a::!l
exception NoSuchProof
let () = CErrors.register_handler begin function
@@ -221,25 +160,8 @@ let discard {CAst.loc;v=id} =
let discard_current () =
if List.is_empty !pstates then raise NoCurrentProof else pstates := List.tl !pstates
-
let discard_all () = pstates := []
-(* [set_proof_mode] sets the proof mode to be used after it's called. It is
- typically called by the Proof Mode command. *)
-let set_proof_mode m id =
- pstates := List.map
- (fun ps -> if pf_name_eq id ps then { ps with mode = m } else ps)
- !pstates;
- update_proof_mode ()
-
-let set_proof_mode mn =
- set_proof_mode (find_proof_mode mn) (get_current_proof_name ())
-
-let activate_proof_mode mode =
- CEphemeron.iter_opt (find_proof_mode mode) (fun x -> x.set ())
-let disactivate_current_proof_mode () =
- CEphemeron.iter_opt !current_proof_mode (fun x -> x.reset ())
-
(** [start_proof sigma id pl str goals terminator] starts a proof of name
[id] with goals [goals] (a list of pairs of environment and
conclusion); [str] describes what kind of theorem/definition this
@@ -254,9 +176,8 @@ let start_proof sigma name ?(pl=UState.default_univ_decl) kind goals terminator
proof = Proof.start ~name ~poly:(pi2 kind) sigma goals;
endline_tactic = None;
section_vars = None;
- mode = find_proof_mode "No";
- universe_decl = pl;
- strength = kind } in
+ strength = kind;
+ universe_decl = pl } in
push initial_state pstates
let start_dependent_proof name ?(pl=UState.default_univ_decl) kind goals terminator =
@@ -265,9 +186,8 @@ let start_dependent_proof name ?(pl=UState.default_univ_decl) kind goals termina
proof = Proof.dependent_start ~name ~poly:(pi2 kind) goals;
endline_tactic = None;
section_vars = None;
- mode = find_proof_mode "No";
- universe_decl = pl;
- strength = kind } in
+ strength = kind;
+ universe_decl = pl } in
push initial_state pstates
let get_used_variables () = (cur_pstate ()).section_vars
@@ -478,7 +398,7 @@ end
let freeze ~marshallable =
if marshallable then CErrors.anomaly (Pp.str"full marshalling of proof state not supported.")
else !pstates
-let unfreeze s = pstates := s; update_proof_mode ()
+let unfreeze s = pstates := s
let proof_of_state = function { proof }::_ -> proof | _ -> raise NoCurrentProof
let copy_terminators ~src ~tgt =
assert(List.length src = List.length tgt);
diff --git a/proofs/proof_global.mli b/proofs/proof_global.mli
index e762f3b7dc..40920f51a3 100644
--- a/proofs/proof_global.mli
+++ b/proofs/proof_global.mli
@@ -13,7 +13,6 @@
environment. *)
type t
-
val there_are_pending_proofs : unit -> bool
val check_no_pending_proof : unit -> unit
@@ -139,47 +138,3 @@ val freeze : marshallable:bool -> t
val unfreeze : t -> unit
val proof_of_state : t -> Proof.t
val copy_terminators : src:t -> tgt:t -> t
-
-
-(**********************************************************)
-(* Proof Mode API *)
-(* The current Proof Mode API is deprecated and a new one *)
-(* will be (hopefully) defined in 8.8 *)
-(**********************************************************)
-
-(** Type of proof modes :
- - A name
- - A function [set] to set it *from standard mode*
- - A function [reset] to reset the *standard mode* from it
-
-*)
-type proof_mode_name = string
-type proof_mode = {
- name : proof_mode_name ;
- set : unit -> unit ;
- reset : unit -> unit
-}
-
-(** Registers a new proof mode which can then be adressed by name
- in [set_default_proof_mode].
- One mode is already registered - the standard mode - named "No",
- It corresponds to Coq default setting are they are set when coqtop starts. *)
-val register_proof_mode : proof_mode -> unit
-(* Can't make this deprecated due to limitations of camlp5 *)
-(* [@@ocaml.deprecated "the current proof mode API is deprecated, use with care, see PR #459 and #566 "] *)
-
-val proof_mode_opt_name : string list
-
-val get_default_proof_mode_name : unit -> proof_mode_name
-[@@ocaml.deprecated "the current proof mode API is deprecated, use with care, see PR #459 and #566 "]
-
-(** [set_proof_mode] sets the proof mode to be used after it's called. It is
- typically called by the Proof Mode command. *)
-val set_proof_mode : proof_mode_name -> unit
-[@@ocaml.deprecated "the current proof mode API is deprecated, use with care, see PR #459 and #566 "]
-
-val activate_proof_mode : proof_mode_name -> unit
-[@@ocaml.deprecated "the current proof mode API is deprecated, use with care, see PR #459 and #566 "]
-
-val disactivate_current_proof_mode : unit -> unit
-[@@ocaml.deprecated "the current proof mode API is deprecated, use with care, see PR #459 and #566 "]
diff --git a/stm/asyncTaskQueue.ml b/stm/asyncTaskQueue.ml
index 2f8129bbfd..be8ef24a09 100644
--- a/stm/asyncTaskQueue.ml
+++ b/stm/asyncTaskQueue.ml
@@ -118,18 +118,38 @@ module Make(T : Task) () = struct
let spawn id =
let name = Printf.sprintf "%s:%d" !T.name id in
let proc, ic, oc =
+ (* Filter arguments for slaves. *)
let rec set_slave_opt = function
| [] -> !async_proofs_flags_for_workers @
["-worker-id"; name;
"-async-proofs-worker-priority";
- CoqworkmgrApi.(string_of_priority !async_proofs_worker_priority)]
- | ("-emacs"|"-emacs-U"|"-batch")::tl -> set_slave_opt tl
- | ("-async-proofs" |"-vio2vo"
+ CoqworkmgrApi.(string_of_priority !async_proofs_worker_priority)]
+ (* Options to discard: 0 arguments *)
+ | ("-emacs"|"-emacs-U"|"-batch")::tl ->
+ set_slave_opt tl
+ (* Options to discard: 1 argument *)
+ | ("-async-proofs" |"-vio2vo" | "-o"
|"-load-vernac-source" |"-l" |"-load-vernac-source-verbose" |"-lv"
|"-compile" |"-compile-verbose"
+ |"-async-proofs-cache"
|"-async-proofs-worker-priority" |"-worker-id") :: _ :: tl ->
set_slave_opt tl
- | x::tl -> x :: set_slave_opt tl in
+ (* We need to pass some options with one argument *)
+ | ( "-I" | "-include" | "-top" | "-topfile" | "-coqlib" | "-exclude-dir" | "-compat"
+ | "-load-ml-object" | "-load-ml-source" | "-require" | "-w" | "-color" | "-init-file"
+ | "-profile-ltac-cutoff" | "-main-channel" | "-control-channel" | "-mangle-names"
+ | "-diffs" | "-mangle-name" | "-dump-glob" | "-bytecode-compiler" | "-native-compiler" as x) :: a :: tl ->
+ x :: a :: set_slave_opt tl
+ (* We need to pass some options with two arguments *)
+ | ( "-R" | "-Q" as x) :: a1 :: a2 :: tl ->
+ x :: a1 :: a2 :: set_slave_opt tl
+ (* Finally we pass all options starting in '-'; check this is safe w.r.t the weird vio* option set *)
+ | x :: tl when x.[0] = '-' ->
+ x :: set_slave_opt tl
+ (* We assume this is a file, filter out *)
+ | _ :: tl ->
+ set_slave_opt tl
+ in
let args =
Array.of_list (set_slave_opt (List.tl (Array.to_list Sys.argv))) in
let env = Array.append (T.extra_env ()) (Unix.environment ()) in
diff --git a/stm/stm.ml b/stm/stm.ml
index 8ed7f2c866..0165b3c029 100644
--- a/stm/stm.ml
+++ b/stm/stm.ml
@@ -126,8 +126,6 @@ type aast = {
}
let pr_ast { expr; indentation } = Pp.(int indentation ++ str " " ++ Ppvernac.pr_vernac expr)
-let default_proof_mode () = Proof_global.get_default_proof_mode_name () [@ocaml.warning "-3"]
-
(* Commands piercing opaque *)
let may_pierce_opaque = function
| VernacPrint _
@@ -146,13 +144,13 @@ let update_global_env () =
module Vcs_ = Vcs.Make(Stateid.Self)
type future_proof = Proof_global.closed_proof_output Future.computation
-type proof_mode = string
+
type depth = int
type branch_type =
[ `Master
- | `Proof of proof_mode * depth
+ | `Proof of depth
| `Edit of
- proof_mode * Stateid.t * Stateid.t * Vernacextend.vernac_qed_type * Vcs_.Branch.t ]
+ Stateid.t * Stateid.t * Vernacextend.vernac_qed_type * Vcs_.Branch.t ]
(* TODO 8.7 : split commands and tactics, since this type is too messy now *)
type cmd_t = {
ctac : bool; (* is a tactic *)
@@ -203,10 +201,10 @@ let summary_pstate = Evarutil.meta_counter_summary_tag,
Obligations.program_tcc_summary_tag
type cached_state =
- | Empty
- | Error of Exninfo.iexn
- | Valid of Vernacstate.t
-
+ | EmptyState
+ | ParsingState of Vernacstate.Parser.state
+ | FullState of Vernacstate.t
+ | ErrorState of Vernacstate.Parser.state option * Exninfo.iexn
type branch = Vcs_.Branch.t * branch_type Vcs_.branch_info
type backup = { mine : branch; others : branch list }
@@ -214,10 +212,16 @@ type 'vcs state_info = { (* TODO: Make this record private to VCS *)
mutable n_reached : int; (* debug cache: how many times was computed *)
mutable n_goals : int; (* open goals: indentation *)
mutable state : cached_state; (* state value *)
+ mutable proof_mode : Pvernac.proof_mode option;
mutable vcs_backup : 'vcs option * backup option;
}
-let default_info () =
- { n_reached = 0; n_goals = 0; state = Empty; vcs_backup = None,None }
+let default_info proof_mode =
+ {
+ n_reached = 0; n_goals = 0;
+ state = EmptyState;
+ proof_mode;
+ vcs_backup = (None,None);
+ }
module DynBlockData : Dyn.S = Dyn.Make ()
@@ -256,15 +260,15 @@ end = struct (* {{{ *)
List.fold_left max 0
(CList.map_filter
(function
- | { Vcs_.kind = `Proof (_,n) } -> Some n
+ | { Vcs_.kind = `Proof n } -> Some n
| { Vcs_.kind = `Edit _ } -> Some 1
| _ -> None)
(List.map (Vcs_.get_branch vcs) (Vcs_.branches vcs)))
let find_proof_at_depth vcs pl =
try List.find (function
- | _, { Vcs_.kind = `Proof(m, n) } -> Int.equal n pl
- | _, { Vcs_.kind = `Edit _ } -> anomaly(Pp.str "find_proof_at_depth.")
+ | _, { Vcs_.kind = `Proof n } -> Int.equal n pl
+ | _, { Vcs_.kind = `Edit _ } -> anomaly(Pp.str "find_proof_at_depth")
| _ -> false)
(List.map (fun h -> h, Vcs_.get_branch vcs h) (Vcs_.branches vcs))
with Not_found -> failwith "find_proof_at_depth"
@@ -326,7 +330,7 @@ module VCS : sig
type vcs = (branch_type, transaction, vcs state_info, box) Vcs_.t
- val init : stm_doc_type -> id -> doc
+ val init : stm_doc_type -> id -> Vernacstate.Parser.state -> doc
(* val get_type : unit -> stm_doc_type *)
val set_ldir : Names.DirPath.t -> unit
val get_ldir : unit -> Names.DirPath.t
@@ -339,7 +343,7 @@ module VCS : sig
val branches : unit -> Branch.t list
val get_branch : Branch.t -> branch_type branch_info
val get_branch_pos : Branch.t -> id
- val new_node : ?id:Stateid.t -> unit -> id
+ val new_node : ?id:Stateid.t -> Pvernac.proof_mode option -> unit -> id
val merge : id -> ours:transaction -> ?into:Branch.t -> Branch.t -> unit
val rewrite_merge : id -> ours:transaction -> at:id -> Branch.t -> unit
val delete_branch : Branch.t -> unit
@@ -356,6 +360,10 @@ module VCS : sig
val goals : id -> int -> unit
val set_state : id -> cached_state -> unit
val get_state : id -> cached_state
+ val set_parsing_state : id -> Vernacstate.Parser.state -> unit
+ val get_parsing_state : id -> Vernacstate.Parser.state option
+ val get_proof_mode : id -> Pvernac.proof_mode option
+ val set_proof_mode : id -> Pvernac.proof_mode option -> unit
(* cuts from start -> stop, raising Expired if some nodes are not there *)
val slice : block_start:id -> block_stop:id -> vcs
@@ -369,7 +377,8 @@ module VCS : sig
val proof_nesting : unit -> int
val checkout_shallowest_proof_branch : unit -> unit
- val propagate_sideff : action:seff_t -> unit
+ val propagate_sideff : action:seff_t -> Stateid.t list
+ val propagate_qed : unit -> unit
val gc : unit -> unit
@@ -411,11 +420,11 @@ end = struct (* {{{ *)
| Qed { qast } -> Pp.string_of_ppcmds (pr_ast qast) in
let is_green id =
match get_info vcs id with
- | Some { state = Valid _ } -> true
+ | Some { state = FullState _ } -> true
| _ -> false in
let is_red id =
match get_info vcs id with
- | Some { state = Error _ } -> true
+ | Some { state = ErrorState _ } -> true
| _ -> false in
let head = current_branch vcs in
let heads =
@@ -517,10 +526,11 @@ end = struct (* {{{ *)
let doc_type = ref (Interactive (TopLogical (Names.DirPath.make [])))
let ldir = ref Names.DirPath.empty
- let init dt id =
+ let init dt id ps =
doc_type := dt;
vcs := empty id;
- vcs := set_info !vcs id (default_info ());
+ let info = { (default_info None) with state = ParsingState ps } in
+ vcs := set_info !vcs id info;
dummy_doc
let set_ldir ld =
@@ -545,9 +555,9 @@ end = struct (* {{{ *)
let branches () = branches !vcs
let get_branch head = get_branch !vcs head
let get_branch_pos head = (get_branch head).pos
- let new_node ?(id=Stateid.fresh ()) () =
+ let new_node ?(id=Stateid.fresh ()) proof_mode () =
assert(Vcs_.get_info !vcs id = None);
- vcs := set_info !vcs id (default_info ());
+ vcs := set_info !vcs id (default_info proof_mode);
id
let merge id ~ours ?into branch =
vcs := merge !vcs id ~ours ~theirs:Noop ?into branch
@@ -569,9 +579,39 @@ end = struct (* {{{ *)
| Some x -> x
| None -> raise Vcs_aux.Expired
let set_state id s =
- (get_info id).state <- s;
- if async_proofs_is_master !cur_opt then Hooks.(call state_ready ~doc:dummy_doc (* XXX should be taken in input *) id)
+ let info = get_info id in
+ info.state <- s;
+ let is_full_state_valid = match s with
+ | FullState _ -> true
+ | EmptyState | ErrorState _ | ParsingState _ -> false
+ in
+ if async_proofs_is_master !cur_opt && is_full_state_valid then
+ Hooks.(call state_ready ~doc:dummy_doc (* XXX should be taken in input *) id)
+
let get_state id = (get_info id).state
+
+ let get_parsing_state id =
+ stm_pperr_endline (fun () -> str "retrieve parsing state state " ++ str (Stateid.to_string id) ++ str " }}}");
+ match (get_info id).state with
+ | FullState s -> Some s.Vernacstate.parsing
+ | ParsingState s -> Some s
+ | ErrorState (s,_) -> s
+ | EmptyState -> None
+
+ let set_parsing_state id ps =
+ let info = get_info id in
+ let new_state =
+ match info.state with
+ | FullState s -> assert false
+ | ParsingState s -> assert false
+ | ErrorState _ -> assert false
+ | EmptyState -> ParsingState ps
+ in
+ info.state <- new_state
+
+ let get_proof_mode id = (get_info id).proof_mode
+ let set_proof_mode id pm = (get_info id).proof_mode <- pm
+
let reached id =
let info = get_info id in
info.n_reached <- info.n_reached + 1
@@ -582,28 +622,33 @@ end = struct (* {{{ *)
let checkout_shallowest_proof_branch () =
if List.mem edit_branch (Vcs_.branches !vcs) then begin
- checkout edit_branch;
- match get_branch edit_branch with
- | { kind = `Edit (mode, _,_,_,_) } -> Proof_global.activate_proof_mode mode [@ocaml.warning "-3"]
- | _ -> assert false
+ checkout edit_branch
end else
let pl = proof_nesting () in
try
- let branch, mode = match Vcs_aux.find_proof_at_depth !vcs pl with
- | h, { Vcs_.kind = `Proof (m, _) } -> h, m | _ -> assert false in
- checkout branch;
- stm_prerr_endline (fun () -> "mode:" ^ mode);
- Proof_global.activate_proof_mode mode [@ocaml.warning "-3"]
+ let branch = fst @@ Vcs_aux.find_proof_at_depth !vcs pl in
+ checkout branch
with Failure _ ->
- checkout Branch.master;
- Proof_global.disactivate_current_proof_mode () [@ocaml.warning "-3"]
+ checkout Branch.master
(* copies the transaction on every open branch *)
let propagate_sideff ~action =
+ List.map (fun b ->
+ checkout b;
+ let proof_mode = get_proof_mode @@ get_branch_pos b in
+ let id = new_node proof_mode () in
+ merge id ~ours:(Sideff action) ~into:b Branch.master;
+ id)
+ (List.filter (fun b -> not (Branch.equal b Branch.master)) (branches ()))
+
+ let propagate_qed () =
List.iter (fun b ->
checkout b;
- let id = new_node () in
- merge id ~ours:(Sideff action) ~into:b Branch.master)
+ let proof_mode = get_proof_mode @@ get_branch_pos b in
+ let id = new_node proof_mode () in
+ let parsing = Option.get @@ get_parsing_state (get_branch_pos b) in
+ merge id ~ours:(Sideff CherryPickEnv) ~into:b Branch.master;
+ set_parsing_state id parsing)
(List.filter (fun b -> not (Branch.equal b Branch.master)) (branches ()))
let visit id = Vcs_aux.visit !vcs id
@@ -625,10 +670,12 @@ end = struct (* {{{ *)
let slice ~block_start ~block_stop =
let l = nodes_in_slice ~block_start ~block_stop in
let copy_info v id =
+ let info = get_info id in
Vcs_.set_info v id
- { (get_info id) with state = Empty; vcs_backup = None,None } in
+ { info with state = EmptyState;
+ vcs_backup = None,None } in
let make_shallow = function
- | Valid st -> Valid (Vernacstate.make_shallow st)
+ | FullState st -> FullState (Vernacstate.make_shallow st)
| x -> x
in
let copy_info_w_state v id =
@@ -651,12 +698,14 @@ end = struct (* {{{ *)
let v = copy_info v id in
v) l v in
(* Stm should have reached the beginning of proof *)
- assert (match (get_info block_start).state with Valid _ -> true | _ -> false);
+ assert (match get_state block_start
+ with FullState _ -> true | _ -> false);
(* We put in the new dag the most recent state known to master *)
let rec fill id =
- match (get_info id).state with
- | Empty | Error _ -> fill (Vcs_aux.visit v id).next
- | Valid _ -> copy_info_w_state v id in
+ match get_state id with
+ | EmptyState | ErrorState _ | ParsingState _ -> fill (Vcs_aux.visit v id).next
+ | FullState _ -> copy_info_w_state v id
+ in
let v = fill block_stop in
(* We put in the new dag the first state (since Qed shall run on it,
* see check_task_aux) *)
@@ -753,13 +802,12 @@ end = struct (* {{{ *)
end (* }}} *)
let state_of_id ~doc id =
- try match (VCS.get_info id).state with
- | Valid s -> `Valid (Some s)
- | Error (e,_) -> `Error e
- | Empty -> `Valid None
+ try match VCS.get_state id with
+ | FullState s -> `Valid (Some s)
+ | ErrorState (_,(e,_)) -> `Error e
+ | EmptyState | ParsingState _ -> `Valid None
with VCS.Expired -> `Expired
-
(****** A cache: fills in the nodes of the VCS document with their value ******)
module State : sig
@@ -782,6 +830,7 @@ module State : sig
val fix_exn_ref : (Exninfo.iexn -> Exninfo.iexn) ref
val install_cached : Stateid.t -> unit
+ (* val install_parsing_state : Stateid.t -> unit *)
val is_cached : ?cache:bool -> Stateid.t -> bool
val is_cached_and_valid : ?cache:bool -> Stateid.t -> bool
@@ -804,10 +853,6 @@ module State : sig
val register_root_state : unit -> unit
val restore_root_state : unit -> unit
- (* Only for internal use to catch problems in parse_sentence, should
- be removed in the state handling refactoring. *)
- val cur_id : Stateid.t ref
-
val purify : ('a -> 'b) -> 'a -> 'b
end = struct (* {{{ *)
@@ -824,6 +869,8 @@ end = struct (* {{{ *)
Vernacstate.unfreeze_interp_state st.vernac_state;
cur_id := st.id
+ let invalidate_cur_state () = cur_id := Stateid.dummy
+
type proof_part =
Proof_global.t *
int * (* Evarutil.meta_counter_summary_tag *)
@@ -842,49 +889,58 @@ end = struct (* {{{ *)
Summary.project_from_summary st Util.(pi3 summary_pstate)
let cache_state ~marshallable id =
- VCS.set_state id (Valid (Vernacstate.freeze_interp_state ~marshallable))
+ VCS.set_state id (FullState (Vernacstate.freeze_interp_state ~marshallable))
- let freeze_invalid id iexn = VCS.set_state id (Error iexn)
+ let freeze_invalid id iexn =
+ let ps = VCS.get_parsing_state id in
+ VCS.set_state id (ErrorState (ps,iexn))
let is_cached ?(cache=false) id only_valid =
if Stateid.equal id !cur_id then
try match VCS.get_info id with
- | { state = Empty } when cache -> cache_state ~marshallable:false id; true
+ | ({ state = EmptyState } | { state = ParsingState _ }) when cache -> cache_state ~marshallable:false id; true
| _ -> true
with VCS.Expired -> false
else
- try match VCS.get_info id with
- | { state = Empty } -> false
- | { state = Valid _ } -> true
- | { state = Error _ } -> not only_valid
+ try match VCS.get_state id with
+ | EmptyState | ParsingState _ -> false
+ | FullState _ -> true
+ | ErrorState _ -> not only_valid
with VCS.Expired -> false
let is_cached_and_valid ?cache id = is_cached ?cache id true
let is_cached ?cache id = is_cached ?cache id false
let install_cached id =
- match VCS.get_info id with
- | { state = Valid s } ->
+ match VCS.get_state id with
+ | FullState s ->
Vernacstate.unfreeze_interp_state s;
cur_id := id
- | { state = Error ie } ->
+ | ErrorState (_,ie) ->
Exninfo.iraise ie
- | _ ->
- (* coqc has a 1 slot cache and only for valid states *)
- if not (VCS.is_interactive ()) && Stateid.equal id !cur_id then ()
- else anomaly Pp.(str "installing a non cached state.")
+ | EmptyState | ParsingState _ ->
+ (* coqc has a 1 slot cache and only for valid states *)
+ if (VCS.is_interactive ()) || not (Stateid.equal id !cur_id) then
+ anomaly Pp.(str "installing a non cached state.")
+
+ (*
+ let install_parsing_state id =
+ if not (Stateid.equal id !cur_id) then begin
+ Vernacstate.Parser.install @@ VCS.get_parsing_state id
+ end
+ *)
let get_cached id =
- try match VCS.get_info id with
- | { state = Valid s } -> s
+ try match VCS.get_state id with
+ | FullState s -> s
| _ -> anomaly Pp.(str "not a cached state.")
with VCS.Expired -> anomaly Pp.(str "not a cached state (expired).")
let assign id what =
let open Vernacstate in
- if VCS.get_state id <> Empty then () else
+ if VCS.get_state id <> EmptyState then () else
try match what with
| `Full s ->
let s =
@@ -896,7 +952,7 @@ end = struct (* {{{ *)
~src:(get_cached prev).proof ~tgt:s.proof }
else s
with VCS.Expired -> s in
- VCS.set_state id (Valid s)
+ VCS.set_state id (FullState s)
| `ProofOnly(ontop,(pstate,c1,c2,c3)) ->
if is_cached_and_valid ontop then
let s = get_cached ontop in
@@ -912,7 +968,7 @@ end = struct (* {{{ *)
st
end
} in
- VCS.set_state id (Valid s)
+ VCS.set_state id (FullState s)
with VCS.Expired -> ()
let exn_on id ~valid (e, info) =
@@ -958,7 +1014,7 @@ end = struct (* {{{ *)
with e ->
let (e, info) = CErrors.push e in
let good_id = !cur_id in
- cur_id := Stateid.dummy;
+ invalidate_cur_state ();
VCS.reached id;
let ie =
match Stateid.get info, safe_id with
@@ -1130,7 +1186,7 @@ module Backtrack : sig
val branches_of : Stateid.t -> backup
(* Returns the state that the command should backtract to *)
- val undo_vernac_classifier : vernac_control -> doc:doc -> Stateid.t * vernac_when
+ val undo_vernac_classifier : vernac_control -> doc:doc -> Stateid.t
val get_prev_proof : doc:doc -> Stateid.t -> Proof.t option
end = struct (* {{{ *)
@@ -1205,30 +1261,30 @@ end = struct (* {{{ *)
try
match Vernacprop.under_control v with
| VernacResetInitial ->
- Stateid.initial, VtNow
+ Stateid.initial
| VernacResetName {CAst.v=name} ->
- let id = VCS.get_branch_pos (VCS.current_branch ()) in
+ let id = VCS.cur_tip () in
(try
let oid =
fold_until (fun b (id,_,label,_,_) ->
if b then `Stop id else `Cont (List.mem name label))
false id in
- oid, VtNow
+ oid
with Not_found ->
- id, VtNow)
+ id)
| VernacBack n ->
- let id = VCS.get_branch_pos (VCS.current_branch ()) in
+ let id = VCS.cur_tip () in
let oid = fold_until (fun n (id,_,_,_,_) ->
if Int.equal n 0 then `Stop id else `Cont (n-1)) n id in
- oid, VtNow
+ oid
| VernacUndo n ->
- let id = VCS.get_branch_pos (VCS.current_branch ()) in
+ let id = VCS.cur_tip () in
let oid = fold_until back_tactic n id in
- oid, VtLater
+ oid
| VernacUndoTo _
| VernacRestart as e ->
let m = match e with VernacUndoTo m -> m | _ -> 0 in
- let id = VCS.get_branch_pos (VCS.current_branch ()) in
+ let id = VCS.cur_tip () in
let vcs =
match (VCS.get_info id).vcs_backup with
| None, _ -> anomaly Pp.(str"Backtrack: tip with no vcs_backup.")
@@ -1241,15 +1297,15 @@ end = struct (* {{{ *)
0 id in
let oid = fold_until (fun n (id,_,_,_,_) ->
if Int.equal n 0 then `Stop id else `Cont (n-1)) (n-m-1) id in
- oid, VtLater
+ oid
| VernacAbortAll ->
- let id = VCS.get_branch_pos (VCS.current_branch ()) in
+ let id = VCS.cur_tip () in
let oid = fold_until (fun () (id,vcs,_,_,_) ->
match Vcs_.branches vcs with [_] -> `Stop id | _ -> `Cont ())
() id in
- oid, VtLater
+ oid
| VernacBackTo id ->
- Stateid.of_int id, VtNow
+ Stateid.of_int id
| _ -> anomaly Pp.(str "incorrect VtMeta classification")
with
| Not_found ->
@@ -1615,7 +1671,7 @@ end = struct (* {{{ *)
when is_tac expr && State.same_env o n -> (* A pure tactic *)
Some (id, `ProofOnly (prev, State.proof_part_of_frozen n))
| Some _, Some s ->
- msg_debug (Pp.str "STM: sending back a fat state");
+ if !Flags.debug then msg_debug (Pp.str "STM: sending back a fat state");
Some (id, `Full s)
| _, Some s -> Some (id, `Full s) in
let rec aux seen = function
@@ -2331,8 +2387,8 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
(Proofview.Goal.goal gl) goals_to_admit then
Proofview.give_up else Proofview.tclUNIT ()
end in
- match (VCS.get_info base_state).state with
- | Valid { Vernacstate.proof } ->
+ match VCS.get_state base_state with
+ | FullState { Vernacstate.proof } ->
Proof_global.unfreeze proof;
Proof_global.with_current_proof (fun _ p ->
feedback ~id:id Feedback.AddedAxiom;
@@ -2469,7 +2525,7 @@ let known_state ~doc ?(redefine_qed=false) ~cache id =
VCS.create_proof_task_box nodes ~qed:id ~block_start;
begin match brinfo, qed.fproof with
| { VCS.kind = `Edit _ }, None -> assert false
- | { VCS.kind = `Edit (_,_,_, okeep, _) }, Some (ofp, cancel) ->
+ | { VCS.kind = `Edit (_,_, okeep, _) }, Some (ofp, cancel) ->
assert(redefine_qed = true);
if okeep <> keep then
msg_warning(strbrk("The command closing the proof changed. "
@@ -2655,7 +2711,7 @@ let new_doc { doc_type ; iload_path; require_libs; stm_options } =
(* We must reset the whole state before creating a document! *)
State.restore_root_state ();
- let doc = VCS.init doc_type Stateid.initial in
+ let doc = VCS.init doc_type Stateid.initial (Vernacstate.Parser.init ()) in
(* Set load path; important, this has to happen before we declare
the library below as [Declaremods/Library] will infer the module
@@ -2723,16 +2779,8 @@ let observe ~doc id =
let finish ~doc =
let head = VCS.current_branch () in
- let doc =observe ~doc (VCS.get_branch_pos head) in
- VCS.print ();
- (* EJGA: Setting here the proof state looks really wrong, and it
- hides true bugs cf bug #5363. Also, what happens with observe? *)
- (* Some commands may by side effect change the proof mode *)
- (match VCS.get_branch head with
- | { VCS.kind = `Edit (mode,_,_,_,_) } -> Proof_global.activate_proof_mode mode [@ocaml.warning "-3"]
- | { VCS.kind = `Proof (mode, _) } -> Proof_global.activate_proof_mode mode [@ocaml.warning "-3"]
- | _ -> ()
- ); doc
+ let doc = observe ~doc (VCS.get_branch_pos head) in
+ VCS.print (); doc
let wait ~doc =
let doc = observe ~doc (VCS.get_branch_pos VCS.Branch.master) in
@@ -2809,12 +2857,14 @@ let merge_proof_branch ~valid ?id qast keep brname =
match brinfo with
| { VCS.kind = `Proof _ } ->
VCS.checkout VCS.Branch.master;
- let id = VCS.new_node ?id () in
+ let id = VCS.new_node ?id None () in
+ let parsing = Option.get @@ VCS.get_parsing_state (VCS.cur_tip ()) in
VCS.merge id ~ours:(Qed (qed None)) brname;
+ VCS.set_parsing_state id parsing;
VCS.delete_branch brname;
- VCS.propagate_sideff ~action:CherryPickEnv;
+ VCS.propagate_qed ();
`Ok
- | { VCS.kind = `Edit (mode, qed_id, master_id, _,_) } ->
+ | { VCS.kind = `Edit (qed_id, master_id, _,_) } ->
let ofp =
match VCS.visit qed_id with
| { step = `Qed ({ fproof }, _) } -> fproof
@@ -2846,25 +2896,32 @@ let snapshot_vio ~doc ldir long_f_dot_vo =
let reset_task_queue = Slaves.reset_task_queue
(* Document building *)
-let process_back_meta_command ~newtip ~head oid aast w =
- let id = VCS.new_node ~id:newtip () in
- let { mine; others } = Backtrack.branches_of oid in
+
+(* We process a meta command found in the document *)
+let process_back_meta_command ~newtip ~head oid aast =
let valid = VCS.get_branch_pos head in
+ let old_parsing = Option.get @@ VCS.get_parsing_state oid in
+
+ (* Merge in and discard all the branches currently open that were not open in `oid` *)
+ let { mine; others } = Backtrack.branches_of oid in
List.iter (fun branch ->
if not (List.mem_assoc branch (mine::others)) then
ignore(merge_proof_branch ~valid aast VtDrop branch))
(VCS.branches ());
+
+ (* We add a node on top of every branch, to represent state aliasing *)
VCS.checkout_shallowest_proof_branch ();
let head = VCS.current_branch () in
List.iter (fun b ->
- if not(VCS.Branch.equal b head) then begin
- VCS.checkout b;
- VCS.commit (VCS.new_node ()) (Alias (oid,aast));
- end)
+ VCS.checkout b;
+ let id = if (VCS.Branch.equal b head) then Some newtip else None in
+ let proof_mode = VCS.get_proof_mode @@ VCS.cur_tip () in
+ let id = VCS.new_node ?id proof_mode () in
+ VCS.commit id (Alias (oid,aast));
+ VCS.set_parsing_state id old_parsing)
(VCS.branches ());
VCS.checkout_shallowest_proof_branch ();
- VCS.commit id (Alias (oid,aast));
- Backtrack.record (); if w == VtNow then ignore(finish ~doc:dummy_doc); `Ok
+ Backtrack.record (); `Ok
let get_allow_nested_proofs =
Goptions.declare_bool_option_and_ref
@@ -2873,6 +2930,7 @@ let get_allow_nested_proofs =
~key:Vernac_classifier.stm_allow_nested_proofs_option_name
~value:false
+(** [process_transaction] adds a node in the document *)
let process_transaction ~doc ?(newtip=Stateid.fresh ())
({ verbose; loc; expr } as x) c =
stm_pperr_endline (fun () -> str "{{{ processing: " ++ pr_ast x);
@@ -2880,18 +2938,21 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
try
let head = VCS.current_branch () in
VCS.checkout head;
+ let head_parsing =
+ Option.get @@ VCS.(get_parsing_state (get_branch_pos head)) in
+ let proof_mode = VCS.(get_proof_mode (get_branch_pos head)) in
let rc = begin
stm_prerr_endline (fun () ->
" classified as: " ^ Vernac_classifier.string_of_vernac_classification c);
match c with
(* Meta *)
| VtMeta, _ ->
- let id, w = Backtrack.undo_vernac_classifier expr ~doc in
- process_back_meta_command ~newtip ~head id x w
+ let id = Backtrack.undo_vernac_classifier expr ~doc in
+ process_back_meta_command ~newtip ~head id x
(* Query *)
| VtQuery, w ->
- let id = VCS.new_node ~id:newtip () in
+ let id = VCS.new_node ~id:newtip proof_mode () in
let queue =
if VCS.is_vio_doc () &&
VCS.((get_branch head).kind = `Master) &&
@@ -2899,10 +2960,11 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
then `SkipQueue
else `MainQueue in
VCS.commit id (mkTransCmd x [] false queue);
- Backtrack.record (); if w == VtNow then ignore(finish ~doc:dummy_doc); `Ok
+ VCS.set_parsing_state id head_parsing;
+ Backtrack.record (); assert (w == VtLater); `Ok
(* Proof *)
- | VtStartProof (mode, guarantee, names), w ->
+ | VtStartProof (guarantee, names), w ->
if not (get_allow_nested_proofs ()) && VCS.proof_nesting () > 0 then
"Nested proofs are not allowed unless you turn option Nested Proofs Allowed on."
@@ -2912,39 +2974,22 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
|> Exninfo.iraise
else
- let id = VCS.new_node ~id:newtip () in
+ let proof_mode = Some (Vernacentries.get_default_proof_mode ()) in
+ let id = VCS.new_node ~id:newtip proof_mode () in
let bname = VCS.mk_branch_name x in
VCS.checkout VCS.Branch.master;
if VCS.Branch.equal head VCS.Branch.master then begin
VCS.commit id (Fork (x, bname, guarantee, names));
- VCS.branch bname (`Proof (mode, VCS.proof_nesting () + 1))
+ VCS.branch bname (`Proof (VCS.proof_nesting () + 1))
end else begin
- VCS.branch bname (`Proof (mode, VCS.proof_nesting () + 1));
+ VCS.branch bname (`Proof (VCS.proof_nesting () + 1));
VCS.merge id ~ours:(Fork (x, bname, guarantee, names)) head
end;
- Proof_global.activate_proof_mode mode [@ocaml.warning "-3"];
- Backtrack.record (); if w == VtNow then ignore(finish ~doc:dummy_doc); `Ok
- | VtProofMode _, VtLater ->
- anomaly(str"VtProofMode must be executed VtNow.")
- | VtProofMode mode, VtNow ->
- let id = VCS.new_node ~id:newtip () in
- VCS.commit id (mkTransCmd x [] false `MainQueue);
- List.iter
- (fun bn -> match VCS.get_branch bn with
- | { VCS.root; kind = `Master; pos } -> ()
- | { VCS.root; kind = `Proof(_,d); pos } ->
- VCS.delete_branch bn;
- VCS.branch ~root ~pos bn (`Proof(mode,d))
- | { VCS.root; kind = `Edit(_,f,q,k,ob); pos } ->
- VCS.delete_branch bn;
- VCS.branch ~root ~pos bn (`Edit(mode,f,q,k,ob)))
- (VCS.branches ());
- VCS.checkout_shallowest_proof_branch ();
- Backtrack.record ();
- ignore(finish ~doc:dummy_doc);
- `Ok
+ VCS.set_parsing_state id head_parsing;
+ Backtrack.record (); assert (w == VtLater); `Ok
+
| VtProofStep { parallel; proof_block_detection = cblock }, w ->
- let id = VCS.new_node ~id:newtip () in
+ let id = VCS.new_node ~id:newtip proof_mode () in
let queue =
match parallel with
| `Yes(solve,abstract) -> `TacQueue (solve, abstract, ref false)
@@ -2954,21 +2999,25 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
If/when and UI will make something useful with this piece of info,
detection should occur here.
detect_proof_block id cblock; *)
- Backtrack.record (); if w == VtNow then ignore(finish ~doc:dummy_doc); `Ok
+ VCS.set_parsing_state id head_parsing;
+ Backtrack.record (); assert (w == VtLater); `Ok
+
| VtQed keep, w ->
let valid = VCS.get_branch_pos head in
- let rc = merge_proof_branch ~valid ~id:newtip x keep head in
+ let rc =
+ merge_proof_branch ~valid ~id:newtip x keep head in
VCS.checkout_shallowest_proof_branch ();
- Backtrack.record (); if w == VtNow then ignore(finish ~doc:dummy_doc);
+ Backtrack.record (); assert (w == VtLater);
rc
(* Side effect in a (still open) proof is replayed on all branches*)
| VtSideff l, w ->
- let id = VCS.new_node ~id:newtip () in
- begin match (VCS.get_branch head).VCS.kind with
- | `Edit _ -> VCS.commit id (mkTransCmd x l true `MainQueue);
- | `Master -> VCS.commit id (mkTransCmd x l false `MainQueue);
- | `Proof _ ->
+ let id = VCS.new_node ~id:newtip proof_mode () in
+ let new_ids =
+ match (VCS.get_branch head).VCS.kind with
+ | `Edit _ -> VCS.commit id (mkTransCmd x l true `MainQueue); []
+ | `Master -> VCS.commit id (mkTransCmd x l false `MainQueue); []
+ | `Proof _ ->
VCS.checkout VCS.Branch.master;
VCS.commit id (mkTransCmd x l true `MainQueue);
(* We can't replay a Definition since universes may be differently
@@ -2976,10 +3025,27 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
let action = match Vernacprop.under_control x.expr with
| VernacDefinition(_, _, DefineBody _) -> CherryPickEnv
| _ -> ReplayCommand x in
- VCS.propagate_sideff ~action;
- end;
+ VCS.propagate_sideff ~action
+ in
VCS.checkout_shallowest_proof_branch ();
- Backtrack.record (); if w == VtNow then ignore(finish ~doc:dummy_doc); `Ok
+ Backtrack.record ();
+ let parsing_state =
+ begin match w with
+ | VtNow ->
+ (* We need to execute to get the new parsing state *)
+ ignore(finish ~doc:dummy_doc);
+ let parsing = Vernacstate.Parser.cur_state () in
+ (* If execution has not been put in cache, we need to save the parsing state *)
+ if (VCS.get_info id).state == EmptyState then VCS.set_parsing_state id parsing;
+ parsing
+ | VtLater -> VCS.set_parsing_state id head_parsing; head_parsing
+ end
+ in
+ (* We save the parsing state on non-master branches *)
+ List.iter (fun id ->
+ if (VCS.get_info id).state == EmptyState then
+ VCS.set_parsing_state id parsing_state) new_ids;
+ `Ok
(* Unknown: we execute it, check for open goals and propagate sideeff *)
| VtUnknown, VtNow ->
@@ -2991,7 +3057,7 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
|> State.exn_on ~valid:Stateid.dummy Stateid.dummy
|> Exninfo.iraise
else
- let id = VCS.new_node ~id:newtip () in
+ let id = VCS.new_node ~id:newtip proof_mode () in
let head_id = VCS.get_branch_pos head in
let _st : unit = Reach.known_state ~doc ~cache:true head_id in (* ensure it is ok *)
let step () =
@@ -3009,9 +3075,8 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
| VernacInstance (_,_ , None, _) -> GuaranteesOpacity
| _ -> Doesn'tGuaranteeOpacity in
VCS.commit id (Fork (x,bname,opacity_of_produced_term (Vernacprop.under_control x.expr),[]));
- let proof_mode = default_proof_mode () in
- VCS.branch bname (`Proof (proof_mode, VCS.proof_nesting () + 1));
- Proof_global.activate_proof_mode proof_mode [@ocaml.warning "-3"];
+ VCS.set_proof_mode id (Some (Vernacentries.get_default_proof_mode ()));
+ VCS.branch bname (`Proof (VCS.proof_nesting () + 1));
end else begin
begin match (VCS.get_branch head).VCS.kind with
| `Edit _ -> VCS.commit id (mkTransCmd x [] in_proof `MainQueue);
@@ -3019,7 +3084,7 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
| `Proof _ ->
VCS.commit id (mkTransCmd x [] in_proof `MainQueue);
(* We hope it can be replayed, but we can't really know *)
- VCS.propagate_sideff ~action:(ReplayCommand x);
+ ignore(VCS.propagate_sideff ~action:(ReplayCommand x));
end;
VCS.checkout_shallowest_proof_branch ();
end in
@@ -3028,6 +3093,17 @@ let process_transaction ~doc ?(newtip=Stateid.fresh ())
| VtUnknown, VtLater ->
anomaly(str"classifier: VtUnknown must imply VtNow.")
+
+ | VtProofMode pm, VtNow ->
+ let proof_mode = Pvernac.lookup_proof_mode pm in
+ let id = VCS.new_node ~id:newtip proof_mode () in
+ VCS.commit id (mkTransCmd x [] false `MainQueue);
+ VCS.set_parsing_state id head_parsing;
+ Backtrack.record (); `Ok
+
+ | VtProofMode _, VtLater ->
+ anomaly(str"classifier: VtProofMode must imply VtNow.")
+
end in
let pr_rc rc = match rc with
| `Ok -> Pp.(seq [str "newtip ("; str (Stateid.to_string (VCS.cur_tip ())); str ")"])
@@ -3051,45 +3127,10 @@ let get_ast ~doc id =
let stop_worker n = Slaves.cancel_worker n
-(* We must parse on top of a state id, it should be something like:
-
- - get parsing information for that state.
- - feed the parsable / parser with the right parsing information.
- - call the parser
-
- Now, the invariant in ensured by the callers, but this is a bit
- problematic.
-*)
-exception End_of_input
-
-let parse_sentence ~doc sid pa =
- (* XXX: Should this restore the previous state?
- Using reach here to try to really get to the
- proper state makes the error resilience code fail *)
- (* Reach.known_state ~cache:`Yes sid; *)
- let cur_tip = VCS.cur_tip () in
- let real_tip = !State.cur_id in
- if not (Stateid.equal sid cur_tip) then
- user_err ~hdr:"Stm.parse_sentence"
- (str "Currently, the parsing api only supports parsing at the tip of the document." ++ fnl () ++
- str "You wanted to parse at: " ++ str (Stateid.to_string sid) ++
- str " but the current tip is: " ++ str (Stateid.to_string cur_tip)) ;
- if not (Stateid.equal sid real_tip) && !Flags.debug && !stm_debug then
- Feedback.msg_debug
- (str "Warning, the real tip doesn't match the current tip." ++
- str "You wanted to parse at: " ++ str (Stateid.to_string sid) ++
- str " but the real tip is: " ++ str (Stateid.to_string real_tip) ++ fnl () ++
- str "This is usually due to use of Stm.observe to evaluate a state different than the tip. " ++
- str "All is good if not parsing changes occur between the two states, however if they do, a problem might occur.");
- Flags.with_option Flags.we_are_parsing (fun () ->
- try
- match Pcoq.Entry.parse Pvernac.main_entry pa with
- | None -> raise End_of_input
- | Some (loc, cmd) -> CAst.make ~loc cmd
- with e when CErrors.noncritical e ->
- let (e, info) = CErrors.push e in
- Exninfo.iraise (e, info))
- ()
+let parse_sentence ~doc sid ~entry pa =
+ let ps = Option.get @@ VCS.get_parsing_state sid in
+ let proof_mode = VCS.get_proof_mode sid in
+ Vernacstate.Parser.parse ps (entry proof_mode) pa
(* You may need to know the len + indentation of previous command to compute
* the indentation of the current one.
@@ -3153,20 +3194,20 @@ let query ~doc ~at ~route s =
State.purify (fun s ->
if Stateid.equal at Stateid.dummy then ignore(finish ~doc:dummy_doc)
else Reach.known_state ~doc ~cache:true at;
- try
- while true do
- let { CAst.loc; v=ast } = parse_sentence ~doc at s in
- let indentation, strlen = compute_indentation ?loc at in
- let st = State.get_cached at in
- let aast = { verbose = true; indentation; strlen; loc; expr = ast } in
- ignore(stm_vernac_interp ~route at st aast)
- done;
- with
- | End_of_input -> ()
- | exn ->
- let iexn = CErrors.push exn in
- Exninfo.iraise iexn
- )
+ let rec loop () =
+ match parse_sentence ~doc at ~entry:Pvernac.main_entry s with
+ | None -> ()
+ | Some (loc, ast) ->
+ let indentation, strlen = compute_indentation ~loc at in
+ let st = State.get_cached at in
+ let aast = {
+ verbose = true; indentation; strlen;
+ loc = Some loc; expr = ast } in
+ ignore(stm_vernac_interp ~route at st aast);
+ loop ()
+ in
+ loop ()
+ )
s
let edit_at ~doc id =
@@ -3204,21 +3245,21 @@ let edit_at ~doc id =
| { step = `Sideff (ReplayCommand _,id) } -> id
| { step = `Sideff _ } -> tip
| { next } -> master_for_br root next in
- let reopen_branch start at_id mode qed_id tip old_branch =
+ let reopen_branch start at_id qed_id tip old_branch =
let master_id, cancel_switch, keep =
(* Hum, this should be the real start_id in the cluster and not next *)
match VCS.visit qed_id with
| { step = `Qed ({ fproof = Some (_,cs); keep },_) } -> start, cs, keep
| _ -> anomaly (str "ProofTask not ending with Qed.") in
VCS.branch ~root:master_id ~pos:id
- VCS.edit_branch (`Edit (mode, qed_id, master_id, keep, old_branch));
+ VCS.edit_branch (`Edit (qed_id, master_id, keep, old_branch));
VCS.delete_boxes_of id;
cancel_switch := true;
Reach.known_state ~doc ~cache:(VCS.is_interactive ()) id;
VCS.checkout_shallowest_proof_branch ();
`Focus { stop = qed_id; start = master_id; tip } in
let no_edit = function
- | `Edit (pm, _,_,_,_) -> `Proof(pm,1)
+ | `Edit (_,_,_,_) -> `Proof 1
| x -> x in
let backto id bn =
List.iter VCS.delete_branch (VCS.branches ());
@@ -3244,17 +3285,17 @@ let edit_at ~doc id =
let focused = List.exists ((=) VCS.edit_branch) (VCS.branches ()) in
let branch_info =
match snd (VCS.get_info id).vcs_backup with
- | Some{ mine = bn, { VCS.kind = `Proof(m,_) }} -> Some(m,bn)
- | Some{ mine = _, { VCS.kind = `Edit(m,_,_,_,bn) }} -> Some (m,bn)
+ | Some{ mine = bn, { VCS.kind = `Proof _ }} -> Some bn
+ | Some{ mine = _, { VCS.kind = `Edit(_,_,_,bn) }} -> Some bn
| _ -> None in
match focused, VCS.proof_task_box_of id, branch_info with
| _, Some _, None -> assert false
- | false, Some { qed = qed_id ; lemma = start }, Some(mode,bn) ->
+ | false, Some { qed = qed_id ; lemma = start }, Some bn ->
let tip = VCS.cur_tip () in
if has_failed qed_id && is_pure qed_id && not !cur_opt.async_proofs_never_reopen_branch
- then reopen_branch start id mode qed_id tip bn
+ then reopen_branch start id qed_id tip bn
else backto id (Some bn)
- | true, Some { qed = qed_id }, Some(mode,bn) ->
+ | true, Some { qed = qed_id }, Some bn ->
if on_cur_branch id then begin
assert false
end else if is_ancestor_of_cur_branch id then begin
@@ -3273,7 +3314,7 @@ let edit_at ~doc id =
end else begin
anomaly(str"Cannot leave an `Edit branch open.")
end
- | false, None, Some(_,bn) -> backto id (Some bn)
+ | false, None, Some bn -> backto id (Some bn)
| false, None, None -> backto id None
in
VCS.print ();
diff --git a/stm/stm.mli b/stm/stm.mli
index b6071fa56b..821ab59a43 100644
--- a/stm/stm.mli
+++ b/stm/stm.mli
@@ -93,16 +93,17 @@ val init_core : unit -> unit
(** [new_doc opt] Creates a new document with options [opt] *)
val new_doc : stm_init_options -> doc * Stateid.t
-(** [parse_sentence sid pa] Reads a sentence from [pa] with parsing
- state [sid] Returns [End_of_input] if the stream ends *)
-val parse_sentence : doc:doc -> Stateid.t -> Pcoq.Parsable.t ->
- Vernacexpr.vernac_control CAst.t
+(** [parse_sentence sid entry pa] Reads a sentence from [pa] with parsing state
+ [sid] and non terminal [entry]. [entry] receives in input the current proof
+ mode. [sid] should be associated with a valid parsing state (which may not
+ be the case if an error was raised at parsing time). *)
+val parse_sentence :
+ doc:doc -> Stateid.t ->
+ entry:(Pvernac.proof_mode option -> 'a Pcoq.Entry.t) -> Pcoq.Parsable.t -> 'a
(* Reminder: A parsable [pa] is constructed using
[Pcoq.Parsable.t stream], where [stream : char Stream.t]. *)
-exception End_of_input
-
(* [add ~ontop ?newtip verbose cmd] adds a new command [cmd] ontop of
the state [ontop].
The [ontop] parameter just asserts that the GUI is on
diff --git a/stm/vernac_classifier.ml b/stm/vernac_classifier.ml
index 09f531ce13..42540af991 100644
--- a/stm/vernac_classifier.ml
+++ b/stm/vernac_classifier.ml
@@ -15,8 +15,6 @@ open CAst
open Vernacextend
open Vernacexpr
-let default_proof_mode () = Proof_global.get_default_proof_mode_name () [@ocaml.warning "-3"]
-
let string_of_parallel = function
| `Yes (solve,abs) ->
"par" ^ if solve then "solve" else "" ^ if abs then "abs" else ""
@@ -32,9 +30,9 @@ let string_of_vernac_type = function
| VtProofStep { parallel; proof_block_detection } ->
"ProofStep " ^ string_of_parallel parallel ^
Option.default "" proof_block_detection
- | VtProofMode s -> "ProofMode " ^ s
| VtQuery -> "Query"
| VtMeta -> "Meta "
+ | VtProofMode _ -> "Proof Mode"
let string_of_vernac_when = function
| VtLater -> "Later"
@@ -57,7 +55,7 @@ let stm_allow_nested_proofs_option_name = ["Nested";"Proofs";"Allowed"]
let options_affecting_stm_scheduling =
[ Attributes.universe_polymorphism_option_name;
stm_allow_nested_proofs_option_name;
- Proof_global.proof_mode_opt_name;
+ Vernacentries.proof_mode_opt_name;
]
let classify_vernac e =
@@ -97,15 +95,15 @@ let classify_vernac e =
| VernacSetOption (_, ["Default";"Proof";"Using"],_) -> VtSideff [], VtNow
(* StartProof *)
| VernacDefinition ((Decl_kinds.DoDischarge,_),({v=i},_),ProveBody _) ->
- VtStartProof(default_proof_mode (),Doesn'tGuaranteeOpacity, idents_of_name i), VtLater
+ VtStartProof(Doesn'tGuaranteeOpacity, idents_of_name i), VtLater
| VernacDefinition (_,({v=i},_),ProveBody _) ->
let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
- VtStartProof(default_proof_mode (),guarantee, idents_of_name i), VtLater
+ VtStartProof(guarantee, idents_of_name i), VtLater
| VernacStartTheoremProof (_,l) ->
let ids = List.map (fun (({v=i}, _), _) -> i) l in
let guarantee = if poly then Doesn'tGuaranteeOpacity else GuaranteesOpacity in
- VtStartProof (default_proof_mode (),guarantee,ids), VtLater
+ VtStartProof (guarantee,ids), VtLater
| VernacFixpoint (discharge,l) ->
let guarantee =
if discharge = Decl_kinds.DoDischarge || poly then Doesn'tGuaranteeOpacity
@@ -115,7 +113,7 @@ let classify_vernac e =
List.fold_left (fun (l,b) ((({v=id},_),_,_,_,p),_) ->
id::l, b || p = None) ([],false) l in
if open_proof
- then VtStartProof (default_proof_mode (),guarantee,ids), VtLater
+ then VtStartProof (guarantee,ids), VtLater
else VtSideff ids, VtLater
| VernacCoFixpoint (discharge,l) ->
let guarantee =
@@ -126,12 +124,14 @@ let classify_vernac e =
List.fold_left (fun (l,b) ((({v=id},_),_,_,p),_) ->
id::l, b || p = None) ([],false) l in
if open_proof
- then VtStartProof (default_proof_mode (),guarantee,ids), VtLater
+ then VtStartProof (guarantee,ids), VtLater
else VtSideff ids, VtLater
(* Sideff: apply to all open branches. usually run on master only *)
| VernacAssumption (_,_,l) ->
let ids = List.flatten (List.map (fun (_,(l,_)) -> List.map (fun (id, _) -> id.v) l) l) in
VtSideff ids, VtLater
+ | VernacPrimitive (id,_,_) ->
+ VtSideff [id.CAst.v], VtLater
| VernacDefinition (_,({v=id},_),DefineBody _) -> VtSideff (idents_of_name id), VtLater
| VernacInductive (_, _,_,l) ->
let ids = List.map (fun (((_,({v=id},_)),_,_,_,cl),_) -> id :: match cl with
@@ -163,7 +163,6 @@ let classify_vernac e =
| VernacExistingClass _ | VernacExistingInstance _
| VernacRegister _
| VernacNameSectionHypSet _
- | VernacDeclareCustomEntry _
| VernacComments _
| VernacDeclareInstance _ -> VtSideff [], VtLater
(* Who knows *)
@@ -177,6 +176,7 @@ let classify_vernac e =
| VernacDeclareModuleType ({v=id},bl,_,_) ->
VtSideff [id], if bl = [] then VtLater else VtNow
(* These commands alter the parser *)
+ | VernacDeclareCustomEntry _
| VernacOpenCloseScope _ | VernacDeclareScope _
| VernacDelimiters _ | VernacBindScope _
| VernacInfix _ | VernacNotation _ | VernacNotationAddFormat _
@@ -184,8 +184,8 @@ let classify_vernac e =
| VernacSyntacticDefinition _
| VernacRequire _ | VernacImport _ | VernacInclude _
| VernacDeclareMLModule _
- | VernacContext _ (* TASSI: unsure *)
- | VernacProofMode _ -> VtSideff [], VtNow
+ | VernacContext _ (* TASSI: unsure *) -> VtSideff [], VtNow
+ | VernacProofMode pm -> VtProofMode pm, VtNow
(* These are ambiguous *)
| VernacInstance _ -> VtUnknown, VtNow
(* Stm will install a new classifier to handle these *)
@@ -211,10 +211,10 @@ let classify_vernac e =
| VernacFail e -> (* Fail Qed or Fail Lemma must not join/fork the DAG *)
(match static_control_classifier e with
| ( VtQuery | VtProofStep _ | VtSideff _
- | VtProofMode _ | VtMeta), _ as x -> x
+ | VtMeta), _ as x -> x
| VtQed _, _ ->
VtProofStep { parallel = `No; proof_block_detection = None },
- VtNow
- | (VtStartProof _ | VtUnknown), _ -> VtQuery, VtLater)
+ VtLater
+ | (VtStartProof _ | VtUnknown | VtProofMode _), _ -> VtQuery, VtLater)
in
static_control_classifier e
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 1043c50f00..070b2356e5 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -98,7 +98,7 @@ let use_bracketing_last_or_and_intro_pattern () =
let () =
declare_bool_option
- { optdepr = false;
+ { optdepr = true;
optname = "bracketing last or-and introduction pattern";
optkey = ["Bracketing";"Last";"Introduction";"Pattern"];
optread = (fun () -> !bracketing_last_or_and_intro_pattern);
diff --git a/tactics/term_dnet.ml b/tactics/term_dnet.ml
index e273891500..e8a66f1889 100644
--- a/tactics/term_dnet.ml
+++ b/tactics/term_dnet.ml
@@ -44,6 +44,7 @@ struct
| DCase of case_info * 't * 't * 't array
| DFix of int array * int * 't array * 't array
| DCoFix of int * 't array * 't array
+ | DInt of Uint63.t
(* special constructors only inside the left-hand side of DCtx or
DApp. Used to encode lists of foralls/letins/apps as contexts *)
@@ -61,6 +62,7 @@ struct
| DCase (_,t1,t2,ta) -> str "case"
| DFix _ -> str "fix"
| DCoFix _ -> str "cofix"
+ | DInt _ -> str "INT"
| DCons ((t,dopt),tl) -> f t ++ (match dopt with
Some t' -> str ":=" ++ f t'
| None -> str "") ++ spc() ++ str "::" ++ spc() ++ f tl
@@ -72,7 +74,7 @@ struct
*)
let map f = function
- | (DRel | DSort | DNil | DRef _) as c -> c
+ | (DRel | DSort | DNil | DRef _ | DInt _) as c -> c
| DCtx (ctx,c) -> DCtx (f ctx, f c)
| DLambda (t,c) -> DLambda (f t, f c)
| DApp (t,u) -> DApp (f t,f u)
@@ -145,6 +147,10 @@ struct
else c
| DCoFix _, _ -> -1 | _, DCoFix _ -> 1
+ | DInt i1, DInt i2 -> Uint63.compare i1 i2
+
+ | DInt _, _ -> -1 | _, DInt _ -> 1
+
| DCons ((t1, ot1), u1), DCons ((t2, ot2), u2) ->
let c = cmp t1 t2 in
if Int.equal c 0 then
@@ -157,7 +163,7 @@ struct
| DNil, DNil -> 0
let fold f acc = function
- | (DRel | DNil | DSort | DRef _) -> acc
+ | (DRel | DNil | DSort | DRef _ | DInt _) -> acc
| DCtx (ctx,c) -> f (f acc ctx) c
| DLambda (t,c) -> f (f acc t) c
| DApp (t,u) -> f (f acc t) u
@@ -169,7 +175,7 @@ struct
| DCons ((t,topt),u) -> f (Option.fold_left f (f acc t) topt) u
let choose f = function
- | (DRel | DSort | DNil | DRef _) -> invalid_arg "choose"
+ | (DRel | DSort | DNil | DRef _ | DInt _) -> invalid_arg "choose"
| DCtx (ctx,c) -> f ctx
| DLambda (t,c) -> f t
| DApp (t,u) -> f u
@@ -185,7 +191,8 @@ struct
if not (Int.equal (compare dummy_cmp (head c1) (head c2)) 0)
then invalid_arg "fold2:compare" else
match c1,c2 with
- | (DRel, DRel | DNil, DNil | DSort, DSort | DRef _, DRef _) -> acc
+ | (DRel, DRel | DNil, DNil | DSort, DSort | DRef _, DRef _
+ | DInt _, DInt _) -> acc
| (DCtx (c1,t1), DCtx (c2,t2)
| DApp (c1,t1), DApp (c2,t2)
| DLambda (c1,t1), DLambda (c2,t2)) -> f (f acc c1 c2) t1 t2
@@ -198,14 +205,15 @@ struct
| DCons ((t1,topt1),u1), DCons ((t2,topt2),u2) ->
f (Option.fold_left2 f (f acc t1 t2) topt1 topt2) u1 u2
| (DRel | DNil | DSort | DRef _ | DCtx _ | DApp _ | DLambda _ | DCase _
- | DFix _ | DCoFix _ | DCons _), _ -> assert false
+ | DFix _ | DCoFix _ | DCons _ | DInt _), _ -> assert false
let map2 (f:'a -> 'b -> 'c) (c1:'a t) (c2:'b t) : 'c t =
let head w = map (fun _ -> ()) w in
if not (Int.equal (compare dummy_cmp (head c1) (head c2)) 0)
then invalid_arg "map2_t:compare" else
match c1,c2 with
- | (DRel, DRel | DSort, DSort | DNil, DNil | DRef _, DRef _) as cc ->
+ | (DRel, DRel | DSort, DSort | DNil, DNil | DRef _, DRef _
+ | DInt _, DInt _) as cc ->
let (c,_) = cc in c
| DCtx (c1,t1), DCtx (c2,t2) -> DCtx (f c1 c2, f t1 t2)
| DLambda (t1,c1), DLambda (t2,c2) -> DLambda (f t1 t2, f c1 c2)
@@ -219,10 +227,10 @@ struct
| DCons ((t1,topt1),u1), DCons ((t2,topt2),u2) ->
DCons ((f t1 t2,Option.lift2 f topt1 topt2), f u1 u2)
| (DRel | DNil | DSort | DRef _ | DCtx _ | DApp _ | DLambda _ | DCase _
- | DFix _ | DCoFix _ | DCons _), _ -> assert false
+ | DFix _ | DCoFix _ | DCons _ | DInt _), _ -> assert false
let terminal = function
- | (DRel | DSort | DNil | DRef _) -> true
+ | (DRel | DSort | DNil | DRef _ | DInt _) -> true
| DLambda _ | DApp _ | DCase _ | DFix _ | DCoFix _ | DCtx _ | DCons _ ->
false
@@ -315,6 +323,7 @@ struct
(pat_of_constr f) (Array.map pat_of_constr ca)
| Proj (p,c) ->
Term (DApp (Term (DRef (ConstRef (Projection.constant p))), pat_of_constr c))
+ | Int i -> Term (DInt i)
and ctx_of_constr ctx c = match Constr.kind c with
| Prod (_,t,c) -> ctx_of_constr (Term(DCons((pat_of_constr t,None),ctx))) c
diff --git a/test-suite/Makefile b/test-suite/Makefile
index 37091a49e5..68acb6f04d 100644
--- a/test-suite/Makefile
+++ b/test-suite/Makefile
@@ -38,14 +38,15 @@ LIB := ..
BIN := $(shell cd ..; pwd)/bin/
COQFLAGS?=
-coqtop := $(BIN)coqtop -coqlib $(LIB) -boot -q -batch -test-mode -R prerequisite TestSuite $(COQFLAGS)
+coqc_boot := $(BIN)coqc -coqlib $(LIB) -boot -q -test-mode -R prerequisite TestSuite $(COQFLAGS)
coqc := $(BIN)coqc -coqlib $(LIB) -R prerequisite TestSuite $(COQFLAGS)
coqchk := $(BIN)coqchk -coqlib $(LIB) -R prerequisite TestSuite
coqdoc := $(BIN)coqdoc
+coqtop := $(BIN)coqtop -coqlib $(LIB) -boot -q -test-mode -R prerequisite TestSuite
coqtopbyte := $(BIN)coqtop.byte
-coqtopload := $(coqtop) -async-proofs-cache force -load-vernac-source
-coqtopcompile := $(coqtop) -async-proofs-cache force -compile
+coqc_interactive := $(coqc) -async-proofs-cache force
+coqc_boot_interactive := $(coqc_boot) -async-proofs-cache force
coqdep := $(BIN)coqdep -coqlib $(LIB)
VERBOSE?=
@@ -60,12 +61,8 @@ SINGLE_QUOTE="
#" # double up on the quotes, in a comment, to appease the emacs syntax highlighter
# wrap the arguments in parens, but only if they exist
get_coq_prog_args_in_parens = $(subst $(SINGLE_QUOTE),,$(if $(call get_coq_prog_args,$(1)), ($(call get_coq_prog_args,$(1)))))
-# get the command to use with this set of arguments; if there's -compile, use coqc, else use coqtop
-has_profile_ltac_or_compile_flag = $(filter "-profile-ltac-cutoff" "-profile-ltac" "-compile",$(call get_coq_prog_args,$(1)))
-get_command_based_on_flags = $(if $(call has_profile_ltac_or_compile_flag,$(1)),$(coqtopcompile),$(coqtopload))
get_set_impredicativity= $(filter "-impredicative-set",$(call get_coq_prog_args,$(1)))
-
bogomips:=
ifneq (,$(wildcard /proc/cpuinfo))
sedbogo := -e "s/bogomips.*: \([0-9]*\).*/\1/p" # i386, ppc
@@ -98,7 +95,7 @@ INTERACTIVE := interactive
UNIT_TESTS := unit-tests
VSUBSYSTEMS := prerequisite success failure $(BUGS) output \
output-modulo-time $(INTERACTIVE) micromega $(COMPLEXITY) modules stm \
- coqdoc ssr
+ coqdoc ssr arithmetic
# All subsystems
SUBSYSTEMS := $(VSUBSYSTEMS) misc bugs ide vio coqchk coqwc coq-makefile tools $(UNIT_TESTS)
@@ -179,6 +176,7 @@ summary:
$(call summary_dir, "Coqdoc tests", coqdoc); \
$(call summary_dir, "tools/ tests", tools); \
$(call summary_dir, "Unit tests", unit-tests); \
+ $(call summary_dir, "Machine arithmetic tests", arithmetic); \
nb_success=`find . -name '*.log' -exec tail -n2 '{}' \; | grep -e $(log_success) | wc -l`; \
nb_failure=`find . -name '*.log' -exec tail -n2 '{}' \; | grep -e $(log_failure) | wc -l`; \
nb_tests=`expr $$nb_success + $$nb_failure`; \
@@ -209,7 +207,7 @@ $(addsuffix .log,$(wildcard bugs/opened/*.v)): %.v.log: %.v
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
if [ $$R = 0 ]; then \
echo $(log_success); \
echo " $<...still active"; \
@@ -231,7 +229,7 @@ $(addsuffix .log,$(wildcard bugs/closed/*.v)): %.v.log: %.v
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
if [ $$R = 0 ]; then \
echo $(log_success); \
echo " $<...Ok"; \
@@ -297,7 +295,7 @@ $(addsuffix .log,$(wildcard prerequisite/*.v)): %.v.log: %.v
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
if [ $$R != 0 ]; then \
echo $(log_failure); \
echo " $<...could not be prepared" ; \
@@ -307,16 +305,16 @@ $(addsuffix .log,$(wildcard prerequisite/*.v)): %.v.log: %.v
echo " $<...correctly prepared" ; \
fi; \
} > "$@"
- @echo "CHK $(shell basename $< .v)"
+ @echo "CHECK $<"
$(HIDE)$(coqchk) -norec TestSuite.$(shell basename $< .v) > $(shell dirname $<)/$(shell basename $< .v).chk.log 2>&1
ssr: $(wildcard ssr/*.v:%.v=%.v.log)
-$(addsuffix .log,$(wildcard ssr/*.v success/*.v micromega/*.v modules/*.v)): %.v.log: %.v $(PREREQUISITELOG)
+$(addsuffix .log,$(wildcard ssr/*.v success/*.v micromega/*.v modules/*.v arithmetic/*.v)): %.v.log: %.v $(PREREQUISITELOG)
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
opts="$(if $(findstring modules/,$<),-R modules Mods)"; \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") $$opts 2>&1; R=$$?; times; \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") $$opts 2>&1; R=$$?; times; \
if [ $$R = 0 ]; then \
echo $(log_success); \
echo " $<...Ok"; \
@@ -326,7 +324,7 @@ $(addsuffix .log,$(wildcard ssr/*.v success/*.v micromega/*.v modules/*.v)): %.v
$(FAIL); \
fi; \
} > "$@"
- @echo "CHK $(shell basename $< .v)"
+ @echo "CHECK $<"
$(HIDE){ \
opts="$(if $(findstring modules/,$<),-R modules Mods -norec Mods.$(shell basename $< .v),-I $(shell dirname $<) -norec $(shell basename $< .v))"; \
$(coqchk) -silent $(call get_set_impredicativity,$<) $$opts 2>&1; R=$$?; \
@@ -342,7 +340,7 @@ $(addsuffix .log,$(wildcard stm/*.v)): %.v.log: %.v
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") -async-proofs on \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") -async-proofs on \
$$opts 2>&1; R=$$?; times; \
if [ $$R = 0 ]; then \
echo $(log_success); \
@@ -353,7 +351,7 @@ $(addsuffix .log,$(wildcard stm/*.v)): %.v.log: %.v
$(FAIL); \
fi; \
} > "$@"
- @echo "CHK $(shell basename $< .v)"
+ @echo "CHECK $<"
$(HIDE){ \
$(coqchk) -silent -I $(shell dirname $<) -norec $(shell basename $< .v) 2>&1; R=$$?; \
if [ $$R != 0 ]; then \
@@ -367,7 +365,7 @@ $(addsuffix .log,$(wildcard failure/*.v)): %.v.log: %.v $(PREREQUISITELOG)
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
if [ $$R = 0 ]; then \
echo $(log_success); \
echo " $<...Ok"; \
@@ -377,7 +375,7 @@ $(addsuffix .log,$(wildcard failure/*.v)): %.v.log: %.v $(PREREQUISITELOG)
$(FAIL); \
fi; \
} > "$@"
- @echo "CHK $(shell basename $< .v)"
+ @echo "CHECK $<"
$(HIDE){ \
$(coqchk) -silent -I $(shell dirname $<) -norec $(shell basename $< .v) 2>&1; R=$$?; \
if [ $$R != 0 ]; then \
@@ -392,7 +390,7 @@ $(addsuffix .log,$(wildcard output/*.v)): %.v.log: %.v %.out $(PREREQUISITELOG)
$(HIDE){ \
echo $(call log_intro,$<); \
output=$*.out.real; \
- $(call get_command_based_on_flags,"$<") "$<" $(call get_coq_prog_args,"$<") 2>&1 \
+ $(coqc_boot_interactive) "$<" $(call get_coq_prog_args,"$<") 2>&1 \
| grep -v "Welcome to Coq" \
| grep -v "\[Loading ML file" \
| grep -v "Skipping rcfile loading" \
@@ -431,7 +429,7 @@ $(addsuffix .log,$(wildcard output-modulo-time/*.v)): %.v.log: %.v %.out
echo $(call log_intro,$<); \
tmpoutput=`mktemp /tmp/coqcheck.XXXXXX`; \
tmpexpected=`mktemp /tmp/coqcheck.XXXXXX`; \
- $(call get_command_based_on_flags,"$<") "$<" $(call get_coq_prog_args,"$<") 2>&1 \
+ $(coqc_boot_interactive) "$<" $(call get_coq_prog_args,"$<") 2>&1 \
| grep -v "Welcome to Coq" \
| grep -v "\[Loading ML file" \
| grep -v "Skipping rcfile loading" \
@@ -486,7 +484,7 @@ $(addsuffix .log,$(wildcard complexity/*.v)): %.v.log: %.v $(PREREQUISITELOG)
$(HIDE){ \
echo $(call log_intro,$<); \
true "extract effective user time"; \
- res=`$(call get_command_based_on_flags,"$<") "$<" $(call get_coq_prog_args,"$<") 2>&1 | sed -n -e "s/Finished transaction in .*(\([0-9]*\.[0-9]*\)u.*)/\1/p" | head -1`; \
+ res=`$(coqc_boot_interactive) "$<" $(call get_coq_prog_args,"$<") 2>&1 | sed -n -e "s/Finished transaction in .*(\([0-9]*\.[0-9]*\)u.*)/\1/p" | head -1`; \
R=$$?; times; \
if [ $$R != 0 ]; then \
echo $(log_failure); \
@@ -517,7 +515,7 @@ $(addsuffix .log,$(wildcard ideal-features/*.v)): %.v.log: %.v $(PREREQUISITELOG
@echo "TEST $< $(call get_coq_prog_args_in_parens,"$<")"
$(HIDE){ \
echo $(call log_intro,$<); \
- $(coqtopcompile) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
+ $(coqc) "$<" $(call get_coq_prog_args,"$<") 2>&1; R=$$?; times; \
if [ $$R != 0 ]; then \
echo $(log_success); \
echo " $<...still wished"; \
@@ -531,7 +529,7 @@ $(addsuffix .log,$(wildcard ideal-features/*.v)): %.v.log: %.v $(PREREQUISITELOG
# Additional dependencies for module tests
$(addsuffix .log,$(wildcard modules/*.v)): %.v.log: modules/Nat.vo modules/plik.vo
modules/%.vo: modules/%.v
- $(HIDE)$(coqtop) -R modules Mods -compile $<
+ $(HIDE)$(coqc) -R modules Mods $<
#######################################################################
# Miscellaneous tests
@@ -550,7 +548,7 @@ $(patsubst %.sh,%.log,$(wildcard misc/*.sh)): %.log: %.sh $(PREREQUISITELOG)
echo $(call log_intro,$<); \
export BIN="$(BIN)"; \
export coqc="$(coqc)"; \
- export coqtop="$(coqtop)"; \
+ export coqtop="$(coqc_boot)"; \
export coqdep="$(coqdep)"; \
export coqtopbyte="$(coqtopbyte)"; \
"$<" 2>&1; R=$$?; times; \
@@ -591,7 +589,7 @@ vio: $(patsubst %.v,%.vio.log,$(wildcard vio/*.v))
@echo "TEST $<"
$(HIDE){ \
$(coqc) -quick -R vio vio $* 2>&1 && \
- $(coqtop) -R vio vio -vio2vo $*.vio 2>&1 && \
+ $(coqc) -R vio vio -vio2vo $*.vio 2>&1 && \
$(coqchk) -R vio vio -norec $(subst /,.,$*) 2>&1; \
if [ $$? = 0 ]; then \
echo $(log_success); \
diff --git a/test-suite/arithmetic/add.v b/test-suite/arithmetic/add.v
new file mode 100644
index 0000000000..fb7eb1d53c
--- /dev/null
+++ b/test-suite/arithmetic/add.v
@@ -0,0 +1,18 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 2 + 3 = 5).
+Check (eq_refl 5 <: 2 + 3 = 5).
+Check (eq_refl 5 <<: 2 + 3 = 5).
+
+Definition compute1 := Eval compute in 2 + 3.
+Check (eq_refl compute1 : 5 = 5).
+
+Check (eq_refl : 9223372036854775807 + 1 = 0).
+Check (eq_refl 0 <: 9223372036854775807 + 1 = 0).
+Check (eq_refl 0 <<: 9223372036854775807 + 1 = 0).
+Definition compute2 := Eval compute in 9223372036854775807 + 1.
+Check (eq_refl compute2 : 0 = 0).
diff --git a/test-suite/arithmetic/addc.v b/test-suite/arithmetic/addc.v
new file mode 100644
index 0000000000..432aec0291
--- /dev/null
+++ b/test-suite/arithmetic/addc.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 2 +c 3 = C0 5).
+Check (eq_refl (C0 5) <: 2 +c 3 = C0 5).
+Check (eq_refl (C0 5) <<: 2 +c 3 = C0 5).
+Definition compute1 := Eval compute in 2 +c 3.
+Check (eq_refl compute1 : C0 5 = C0 5).
+
+Check (eq_refl : 9223372036854775807 +c 2 = C1 1).
+Check (eq_refl (C1 1) <: 9223372036854775807 +c 2 = C1 1).
+Check (eq_refl (C1 1) <<: 9223372036854775807 +c 2 = C1 1).
+Definition compute2 := Eval compute in 9223372036854775807 +c 2.
+Check (eq_refl compute2 : C1 1 = C1 1).
diff --git a/test-suite/arithmetic/addcarryc.v b/test-suite/arithmetic/addcarryc.v
new file mode 100644
index 0000000000..a4430769ca
--- /dev/null
+++ b/test-suite/arithmetic/addcarryc.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : addcarryc 2 3 = C0 6).
+Check (eq_refl (C0 6) <: addcarryc 2 3 = C0 6).
+Check (eq_refl (C0 6) <<: addcarryc 2 3 = C0 6).
+Definition compute1 := Eval compute in addcarryc 2 3.
+Check (eq_refl compute1 : C0 6 = C0 6).
+
+Check (eq_refl : addcarryc 9223372036854775807 2 = C1 2).
+Check (eq_refl (C1 2) <: addcarryc 9223372036854775807 2 = C1 2).
+Check (eq_refl (C1 2) <<: addcarryc 9223372036854775807 2 = C1 2).
+Definition compute2 := Eval compute in addcarryc 9223372036854775807 2.
+Check (eq_refl compute2 : C1 2 = C1 2).
diff --git a/test-suite/arithmetic/addmuldiv.v b/test-suite/arithmetic/addmuldiv.v
new file mode 100644
index 0000000000..72b0164b49
--- /dev/null
+++ b/test-suite/arithmetic/addmuldiv.v
@@ -0,0 +1,12 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : addmuldiv 32 3 5629499534213120 = 12887523328).
+Check (eq_refl 12887523328 <: addmuldiv 32 3 5629499534213120 = 12887523328).
+Check (eq_refl 12887523328 <<: addmuldiv 32 3 5629499534213120 = 12887523328).
+
+Definition compute2 := Eval compute in addmuldiv 32 3 5629499534213120.
+Check (eq_refl compute2 : 12887523328 = 12887523328).
diff --git a/test-suite/arithmetic/compare.v b/test-suite/arithmetic/compare.v
new file mode 100644
index 0000000000..a8d1ea1226
--- /dev/null
+++ b/test-suite/arithmetic/compare.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 1 ?= 1 = Eq).
+Check (eq_refl Eq <: 1 ?= 1 = Eq).
+Check (eq_refl Eq <<: 1 ?= 1 = Eq).
+Definition compute1 := Eval compute in 1 ?= 1.
+Check (eq_refl compute1 : Eq = Eq).
+
+Check (eq_refl : 1 ?= 2 = Lt).
+Check (eq_refl Lt <: 1 ?= 2 = Lt).
+Check (eq_refl Lt <<: 1 ?= 2 = Lt).
+Definition compute2 := Eval compute in 1 ?= 2.
+Check (eq_refl compute2 : Lt = Lt).
+
+Check (eq_refl : 9223372036854775807 ?= 0 = Gt).
+Check (eq_refl Gt <: 9223372036854775807 ?= 0 = Gt).
+Check (eq_refl Gt <<: 9223372036854775807 ?= 0 = Gt).
+Definition compute3 := Eval compute in 9223372036854775807 ?= 0.
+Check (eq_refl compute3 : Gt = Gt).
diff --git a/test-suite/arithmetic/div.v b/test-suite/arithmetic/div.v
new file mode 100644
index 0000000000..0ee0b91580
--- /dev/null
+++ b/test-suite/arithmetic/div.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 6 / 3 = 2).
+Check (eq_refl 2 <: 6 / 3 = 2).
+Check (eq_refl 2 <<: 6 / 3 = 2).
+Definition compute1 := Eval compute in 6 / 3.
+Check (eq_refl compute1 : 2 = 2).
+
+Check (eq_refl : 3 / 2 = 1).
+Check (eq_refl 1 <: 3 / 2 = 1).
+Check (eq_refl 1 <<: 3 / 2 = 1).
+Definition compute2 := Eval compute in 3 / 2.
+Check (eq_refl compute2 : 1 = 1).
diff --git a/test-suite/arithmetic/diveucl.v b/test-suite/arithmetic/diveucl.v
new file mode 100644
index 0000000000..8f88a0f356
--- /dev/null
+++ b/test-suite/arithmetic/diveucl.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : diveucl 6 3 = (2,0)).
+Check (eq_refl (2,0) <: diveucl 6 3 = (2,0)).
+Check (eq_refl (2,0) <<: diveucl 6 3 = (2,0)).
+Definition compute1 := Eval compute in diveucl 6 3.
+Check (eq_refl compute1 : (2,0) = (2,0)).
+
+Check (eq_refl : diveucl 5 3 = (1,2)).
+Check (eq_refl (1,2) <: diveucl 5 3 = (1,2)).
+Check (eq_refl (1,2) <<: diveucl 5 3 = (1,2)).
+Definition compute2 := Eval compute in diveucl 5 3.
+Check (eq_refl compute2 : (1,2) = (1,2)).
diff --git a/test-suite/arithmetic/diveucl_21.v b/test-suite/arithmetic/diveucl_21.v
new file mode 100644
index 0000000000..7e12a08906
--- /dev/null
+++ b/test-suite/arithmetic/diveucl_21.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : diveucl_21 1 1 2 = (4611686018427387904,1)).
+Check (eq_refl (4611686018427387904,1) <: diveucl_21 1 1 2 = (4611686018427387904,1)).
+Check (eq_refl (4611686018427387904,1) <<: diveucl_21 1 1 2 = (4611686018427387904,1)).
+Definition compute1 := Eval compute in diveucl_21 1 1 2.
+Check (eq_refl compute1 : (4611686018427387904,1) = (4611686018427387904,1)).
+
+Check (eq_refl : diveucl_21 3 1 2 = (4611686018427387904, 1)).
+Check (eq_refl (4611686018427387904, 1) <: diveucl_21 3 1 2 = (4611686018427387904, 1)).
+Check (eq_refl (4611686018427387904, 1) <<: diveucl_21 3 1 2 = (4611686018427387904, 1)).
+Definition compute2 := Eval compute in diveucl_21 3 1 2.
+Check (eq_refl compute2 : (4611686018427387904, 1) = (4611686018427387904, 1)).
diff --git a/test-suite/arithmetic/eqb.v b/test-suite/arithmetic/eqb.v
new file mode 100644
index 0000000000..dcc0b71f6d
--- /dev/null
+++ b/test-suite/arithmetic/eqb.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 1 == 1 = true).
+Check (eq_refl true <: 1 == 1 = true).
+Check (eq_refl true <<: 1 == 1 = true).
+Definition compute1 := Eval compute in 1 == 1.
+Check (eq_refl compute1 : true = true).
+
+Check (eq_refl : 9223372036854775807 == 0 = false).
+Check (eq_refl false <: 9223372036854775807 == 0 = false).
+Check (eq_refl false <<: 9223372036854775807 == 0 = false).
+Definition compute2 := Eval compute in 9223372036854775807 == 0.
+Check (eq_refl compute2 : false = false).
diff --git a/test-suite/arithmetic/head0.v b/test-suite/arithmetic/head0.v
new file mode 100644
index 0000000000..f4234d2605
--- /dev/null
+++ b/test-suite/arithmetic/head0.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : head0 3 = 61).
+Check (eq_refl 61 <: head0 3 = 61).
+Check (eq_refl 61 <<: head0 3 = 61).
+Definition compute1 := Eval compute in head0 3.
+Check (eq_refl compute1 : 61 = 61).
+
+Check (eq_refl : head0 4611686018427387904 = 0).
+Check (eq_refl 0 <: head0 4611686018427387904 = 0).
+Check (eq_refl 0 <<: head0 4611686018427387904 = 0).
+Definition compute2 := Eval compute in head0 4611686018427387904.
+Check (eq_refl compute2 : 0 = 0).
+
+Check (eq_refl : head0 0 = 63).
+Check (eq_refl 63 <: head0 0 = 63).
+Check (eq_refl 63 <<: head0 0 = 63).
+Definition compute3 := Eval compute in head0 0.
+Check (eq_refl compute3 : 63 = 63).
diff --git a/test-suite/arithmetic/isint.v b/test-suite/arithmetic/isint.v
new file mode 100644
index 0000000000..c215caa878
--- /dev/null
+++ b/test-suite/arithmetic/isint.v
@@ -0,0 +1,50 @@
+(* This file tests the check that arithmetic operations use to know if their
+arguments are ground. The various test cases correspond to possible
+optimizations of these tests made by the compiler. *)
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Section test.
+
+Variable m n : int.
+
+Check (eq_refl : (fun x => x + 3) m = m + 3).
+Check (eq_refl (m + 3) <: (fun x => x + 3) m = m + 3).
+Check (eq_refl (m + 3) <<: (fun x => x + 3) m = m + 3).
+Definition compute1 := Eval compute in (fun x => x + 3) m.
+Check (eq_refl compute1 : m + 3 = m + 3).
+
+Check (eq_refl : (fun x => 3 + x) m = 3 + m).
+Check (eq_refl (3 + m) <: (fun x => 3 + x) m = 3 + m).
+Check (eq_refl (3 + m) <<: (fun x => 3 + x) m = 3 + m).
+Definition compute2 := Eval compute in (fun x => 3 + x) m.
+Check (eq_refl compute2 : 3 + m = 3 + m).
+
+Check (eq_refl : (fun x y => x + y) m n = m + n).
+Check (eq_refl (m + n) <: (fun x y => x + y) m n = m + n).
+Check (eq_refl (m + n) <<: (fun x y => x + y) m n = m + n).
+Definition compute3 := Eval compute in (fun x y => x + y) m n.
+Check (eq_refl compute3 : m + n = m + n).
+
+Check (eq_refl : (fun x y => x + y) 2 3 = 5).
+Check (eq_refl 5 <: (fun x y => x + y) 2 3 = 5).
+Check (eq_refl 5 <<: (fun x y => x + y) 2 3 = 5).
+Definition compute4 := Eval compute in (fun x y => x + y) 2 3.
+Check (eq_refl compute4 : 5 = 5).
+
+Check (eq_refl : (fun x => x + x) m = m + m).
+Check (eq_refl (m + m) <: (fun x => x + x) m = m + m).
+Check (eq_refl (m + m) <<: (fun x => x + x) m = m + m).
+Definition compute5 := Eval compute in (fun x => x + x) m.
+Check (eq_refl compute5 : m + m = m + m).
+
+Check (eq_refl : (fun x => x + x) 2 = 4).
+Check (eq_refl 4 <: (fun x => x + x) 2 = 4).
+Check (eq_refl 4 <<: (fun x => x + x) 2 = 4).
+Definition compute6 := Eval compute in (fun x => x + x) 2.
+Check (eq_refl compute6 : 4 = 4).
+
+End test.
diff --git a/test-suite/arithmetic/land.v b/test-suite/arithmetic/land.v
new file mode 100644
index 0000000000..0ea6fd90b6
--- /dev/null
+++ b/test-suite/arithmetic/land.v
@@ -0,0 +1,29 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 0 land 0 = 0).
+Check (eq_refl 0 <: 0 land 0 = 0).
+Check (eq_refl 0 <<: 0 land 0 = 0).
+Definition compute1 := Eval compute in 0 land 0.
+Check (eq_refl compute1 : 0 = 0).
+
+Check (eq_refl : 9223372036854775807 land 0 = 0).
+Check (eq_refl 0 <: 9223372036854775807 land 0 = 0).
+Check (eq_refl 0 <<: 9223372036854775807 land 0 = 0).
+Definition compute2 := Eval compute in 9223372036854775807 land 0.
+Check (eq_refl compute2 : 0 = 0).
+
+Check (eq_refl : 0 land 9223372036854775807 = 0).
+Check (eq_refl 0 <: 0 land 9223372036854775807 = 0).
+Check (eq_refl 0 <<: 0 land 9223372036854775807 = 0).
+Definition compute3 := Eval compute in 0 land 9223372036854775807.
+Check (eq_refl compute3 : 0 = 0).
+
+Check (eq_refl : 9223372036854775807 land 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 9223372036854775807 land 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 9223372036854775807 land 9223372036854775807 = 9223372036854775807).
+Definition compute4 := Eval compute in 9223372036854775807 land 9223372036854775807.
+Check (eq_refl compute4 : 9223372036854775807 = 9223372036854775807).
diff --git a/test-suite/arithmetic/leb.v b/test-suite/arithmetic/leb.v
new file mode 100644
index 0000000000..5354919978
--- /dev/null
+++ b/test-suite/arithmetic/leb.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 1 <= 1 = true).
+Check (eq_refl true <: 1 <= 1 = true).
+Check (eq_refl true <<: 1 <= 1 = true).
+Definition compute1 := Eval compute in 1 <= 1.
+Check (eq_refl compute1 : true = true).
+
+Check (eq_refl : 1 <= 2 = true).
+Check (eq_refl true <: 1 <= 2 = true).
+Check (eq_refl true <<: 1 <= 2 = true).
+Definition compute2 := Eval compute in 1 <= 2.
+Check (eq_refl compute2 : true = true).
+
+Check (eq_refl : 9223372036854775807 <= 0 = false).
+Check (eq_refl false <: 9223372036854775807 <= 0 = false).
+Check (eq_refl false <<: 9223372036854775807 <= 0 = false).
+Definition compute3 := Eval compute in 9223372036854775807 <= 0.
+Check (eq_refl compute3 : false = false).
diff --git a/test-suite/arithmetic/lor.v b/test-suite/arithmetic/lor.v
new file mode 100644
index 0000000000..9c3b85c054
--- /dev/null
+++ b/test-suite/arithmetic/lor.v
@@ -0,0 +1,29 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 0 lor 0 = 0).
+Check (eq_refl 0 <: 0 lor 0 = 0).
+Check (eq_refl 0 <<: 0 lor 0 = 0).
+Definition compute1 := Eval compute in 0 lor 0.
+Check (eq_refl compute1 : 0 = 0).
+
+Check (eq_refl : 9223372036854775807 lor 0 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 9223372036854775807 lor 0 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 9223372036854775807 lor 0 = 9223372036854775807).
+Definition compute2 := Eval compute in 9223372036854775807 lor 0.
+Check (eq_refl compute2 : 9223372036854775807 = 9223372036854775807).
+
+Check (eq_refl : 0 lor 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 0 lor 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 0 lor 9223372036854775807 = 9223372036854775807).
+Definition compute3 := Eval compute in 0 lor 9223372036854775807.
+Check (eq_refl compute3 : 9223372036854775807 = 9223372036854775807).
+
+Check (eq_refl : 9223372036854775807 lor 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 9223372036854775807 lor 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 9223372036854775807 lor 9223372036854775807 = 9223372036854775807).
+Definition compute4 := Eval compute in 9223372036854775807 lor 9223372036854775807.
+Check (eq_refl compute4 : 9223372036854775807 = 9223372036854775807).
diff --git a/test-suite/arithmetic/lsl.v b/test-suite/arithmetic/lsl.v
new file mode 100644
index 0000000000..70f3b90140
--- /dev/null
+++ b/test-suite/arithmetic/lsl.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 3 << 61 = 6917529027641081856).
+Check (eq_refl 6917529027641081856 <: 3 << 61 = 6917529027641081856).
+Check (eq_refl 6917529027641081856 <<: 3 << 61 = 6917529027641081856).
+Definition compute1 := Eval compute in 3 << 61.
+Check (eq_refl compute1 : 6917529027641081856 = 6917529027641081856).
+
+Check (eq_refl : 2 << 62 = 0).
+Check (eq_refl 0 <: 2 << 62 = 0).
+Check (eq_refl 0 <<: 2 << 62 = 0).
+Definition compute2 := Eval compute in 2 << 62.
+Check (eq_refl compute2 : 0 = 0).
+
+Check (eq_refl : 9223372036854775807 << 64 = 0).
+Check (eq_refl 0 <: 9223372036854775807 << 64 = 0).
+Check (eq_refl 0 <<: 9223372036854775807 << 64 = 0).
+Definition compute3 := Eval compute in 9223372036854775807 << 64.
+Check (eq_refl compute3 : 0 = 0).
diff --git a/test-suite/arithmetic/lsr.v b/test-suite/arithmetic/lsr.v
new file mode 100644
index 0000000000..c36c24e237
--- /dev/null
+++ b/test-suite/arithmetic/lsr.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 6917529027641081856 >> 61 = 3).
+Check (eq_refl 3 <: 6917529027641081856 >> 61 = 3).
+Check (eq_refl 3 <<: 6917529027641081856 >> 61 = 3).
+Definition compute1 := Eval compute in 6917529027641081856 >> 61.
+Check (eq_refl compute1 : 3 = 3).
+
+Check (eq_refl : 2305843009213693952 >> 62 = 0).
+Check (eq_refl 0 <: 2305843009213693952 >> 62 = 0).
+Check (eq_refl 0 <<: 2305843009213693952 >> 62 = 0).
+Definition compute2 := Eval compute in 2305843009213693952 >> 62.
+Check (eq_refl compute2 : 0 = 0).
+
+Check (eq_refl : 9223372036854775807 >> 64 = 0).
+Check (eq_refl 0 <: 9223372036854775807 >> 64 = 0).
+Check (eq_refl 0 <<: 9223372036854775807 >> 64 = 0).
+Definition compute3 := Eval compute in 9223372036854775807 >> 64.
+Check (eq_refl compute3 : 0 = 0).
diff --git a/test-suite/arithmetic/ltb.v b/test-suite/arithmetic/ltb.v
new file mode 100644
index 0000000000..7ae5ac6493
--- /dev/null
+++ b/test-suite/arithmetic/ltb.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 1 < 1 = false).
+Check (eq_refl false <: 1 < 1 = false).
+Check (eq_refl false <<: 1 < 1 = false).
+Definition compute1 := Eval compute in 1 < 1.
+Check (eq_refl compute1 : false = false).
+
+Check (eq_refl : 1 < 2 = true).
+Check (eq_refl true <: 1 < 2 = true).
+Check (eq_refl true <<: 1 < 2 = true).
+Definition compute2 := Eval compute in 1 < 2.
+Check (eq_refl compute2 : true = true).
+
+Check (eq_refl : 9223372036854775807 < 0 = false).
+Check (eq_refl false <: 9223372036854775807 < 0 = false).
+Check (eq_refl false <<: 9223372036854775807 < 0 = false).
+Definition compute3 := Eval compute in 9223372036854775807 < 0.
+Check (eq_refl compute3 : false = false).
diff --git a/test-suite/arithmetic/lxor.v b/test-suite/arithmetic/lxor.v
new file mode 100644
index 0000000000..b453fc7697
--- /dev/null
+++ b/test-suite/arithmetic/lxor.v
@@ -0,0 +1,29 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 0 lxor 0 = 0).
+Check (eq_refl 0 <: 0 lxor 0 = 0).
+Check (eq_refl 0 <<: 0 lxor 0 = 0).
+Definition compute1 := Eval compute in 0 lxor 0.
+Check (eq_refl compute1 : 0 = 0).
+
+Check (eq_refl : 9223372036854775807 lxor 0 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 9223372036854775807 lxor 0 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 9223372036854775807 lxor 0 = 9223372036854775807).
+Definition compute2 := Eval compute in 9223372036854775807 lxor 0.
+Check (eq_refl compute2 : 9223372036854775807 = 9223372036854775807).
+
+Check (eq_refl : 0 lxor 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 0 lxor 9223372036854775807 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 0 lxor 9223372036854775807 = 9223372036854775807).
+Definition compute3 := Eval compute in 0 lxor 9223372036854775807.
+Check (eq_refl compute3 : 9223372036854775807 = 9223372036854775807).
+
+Check (eq_refl : 9223372036854775807 lxor 9223372036854775807 = 0).
+Check (eq_refl 0 <: 9223372036854775807 lxor 9223372036854775807 = 0).
+Check (eq_refl 0 <<: 9223372036854775807 lxor 9223372036854775807 = 0).
+Definition compute4 := Eval compute in 9223372036854775807 lxor 9223372036854775807.
+Check (eq_refl compute4 : 0 = 0).
diff --git a/test-suite/arithmetic/mod.v b/test-suite/arithmetic/mod.v
new file mode 100644
index 0000000000..5307eed493
--- /dev/null
+++ b/test-suite/arithmetic/mod.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 6 \% 3 = 0).
+Check (eq_refl 0 <: 6 \% 3 = 0).
+Check (eq_refl 0 <<: 6 \% 3 = 0).
+Definition compute1 := Eval compute in 6 \% 3.
+Check (eq_refl compute1 : 0 = 0).
+
+Check (eq_refl : 5 \% 3 = 2).
+Check (eq_refl 2 <: 5 \% 3 = 2).
+Check (eq_refl 2 <<: 5 \% 3 = 2).
+Definition compute2 := Eval compute in 5 \% 3.
+Check (eq_refl compute2 : 2 = 2).
diff --git a/test-suite/arithmetic/mul.v b/test-suite/arithmetic/mul.v
new file mode 100644
index 0000000000..9480e8cd46
--- /dev/null
+++ b/test-suite/arithmetic/mul.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 2 * 3 = 6).
+Check (eq_refl 6 <: 2 * 3 = 6).
+Check (eq_refl 6 <<: 2 * 3 = 6).
+Definition compute1 := Eval compute in 2 * 3.
+Check (eq_refl compute1 : 6 = 6).
+
+Check (eq_refl : 9223372036854775807 * 2 = 9223372036854775806).
+Check (eq_refl 9223372036854775806 <: 9223372036854775807 * 2 = 9223372036854775806).
+Check (eq_refl 9223372036854775806 <<: 9223372036854775807 * 2 = 9223372036854775806).
+Definition compute2 := Eval compute in 9223372036854775807 * 2.
+Check (eq_refl compute2 : 9223372036854775806 = 9223372036854775806).
diff --git a/test-suite/arithmetic/mulc.v b/test-suite/arithmetic/mulc.v
new file mode 100644
index 0000000000..e10855bafa
--- /dev/null
+++ b/test-suite/arithmetic/mulc.v
@@ -0,0 +1,22 @@
+Require Import Cyclic63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 2 *c 3 = WW 0 6).
+Check (eq_refl (WW 0 6) <: 2 *c 3 = WW 0 6).
+Check (eq_refl (WW 0 6) <<: 2 *c 3 = WW 0 6).
+Definition compute1 := Eval compute in 2 *c 3.
+Check (eq_refl compute1 : WW 0 6 = WW 0 6).
+
+Check (eq_refl : 9223372036854775807 *c 2 = WW 1 9223372036854775806).
+Check (eq_refl (WW 1 9223372036854775806) <: 9223372036854775807 *c 2 = WW 1 9223372036854775806).
+Check (eq_refl (WW 1 9223372036854775806) <<: 9223372036854775807 *c 2 = WW 1 9223372036854775806).
+
+Definition compute2 := Eval compute in 9223372036854775807 *c 2.
+Check (eq_refl compute2 : WW 1 9223372036854775806 = WW 1 9223372036854775806).
+
+Check (eq_refl : 0 *c 0 = W0).
+Check (eq_refl (@W0 int) <: 0 *c 0 = W0).
+Check (eq_refl (@W0 int) <<: 0 *c 0 = W0).
diff --git a/test-suite/arithmetic/primitive.v b/test-suite/arithmetic/primitive.v
new file mode 100644
index 0000000000..f62f6109e1
--- /dev/null
+++ b/test-suite/arithmetic/primitive.v
@@ -0,0 +1,12 @@
+Section S.
+ Variable A : Type.
+ Fail Primitive int : let x := A in Set := #int63_type.
+ Fail Primitive add := #int63_add.
+End S.
+
+(* [Primitive] should be forbidden in sections, otherwise its type after cooking
+will be incorrect:
+
+Check int.
+
+*)
diff --git a/test-suite/arithmetic/reduction.v b/test-suite/arithmetic/reduction.v
new file mode 100644
index 0000000000..00e067ac5a
--- /dev/null
+++ b/test-suite/arithmetic/reduction.v
@@ -0,0 +1,28 @@
+Require Import Int63.
+
+Open Scope int63_scope.
+
+Definition div_eucl_plus_one i1 i2 :=
+ let (q,r) := diveucl i1 i2 in
+ (q+1, r+1)%int63.
+
+Definition rcbn := Eval cbn in div_eucl_plus_one 3 2.
+Check (eq_refl : rcbn = (2, 2)).
+
+Definition rcbv := Eval cbv in div_eucl_plus_one 3 2.
+Check (eq_refl : rcbv = (2, 2)).
+
+Definition rvmc := Eval vm_compute in div_eucl_plus_one 3 2.
+Check (eq_refl : rvmc = (2, 2)).
+
+Definition f n m :=
+ match (n ?= 42)%int63 with
+ | Lt => (n + m)%int63
+ | _ => (2*m)%int63
+ end.
+
+Goal forall n, (n ?= 42)%int63 = Gt -> f n 256 = 512%int63.
+ intros. unfold f.
+ cbn. Undo. cbv. (* Test reductions under match clauses *)
+ rewrite H. reflexivity.
+Qed.
diff --git a/test-suite/arithmetic/sub.v b/test-suite/arithmetic/sub.v
new file mode 100644
index 0000000000..1606fd2aa1
--- /dev/null
+++ b/test-suite/arithmetic/sub.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 3 - 2 = 1).
+Check (eq_refl 1 <: 3 - 2 = 1).
+Check (eq_refl 1 <<: 3 - 2 = 1).
+Definition compute1 := Eval compute in 3 - 2.
+Check (eq_refl compute1 : 1 = 1).
+
+Check (eq_refl : 0 - 1 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <: 0 - 1 = 9223372036854775807).
+Check (eq_refl 9223372036854775807 <<: 0 - 1 = 9223372036854775807).
+Definition compute2 := Eval compute in 0 - 1.
+Check (eq_refl compute2 : 9223372036854775807 = 9223372036854775807).
diff --git a/test-suite/arithmetic/subc.v b/test-suite/arithmetic/subc.v
new file mode 100644
index 0000000000..fc4067e48b
--- /dev/null
+++ b/test-suite/arithmetic/subc.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : 3 -c 2 = C0 1).
+Check (eq_refl (C0 1) <: 3 -c 2 = C0 1).
+Check (eq_refl (C0 1) <<: 3 -c 2 = C0 1).
+Definition compute1 := Eval compute in 3 -c 2.
+Check (eq_refl compute1 : C0 1 = C0 1).
+
+Check (eq_refl : 0 -c 1 = C1 9223372036854775807).
+Check (eq_refl (C1 9223372036854775807) <: 0 -c 1 = C1 9223372036854775807).
+Check (eq_refl (C1 9223372036854775807) <<: 0 -c 1 = C1 9223372036854775807).
+Definition compute2 := Eval compute in 0 -c 1.
+Check (eq_refl compute2 : C1 9223372036854775807 = C1 9223372036854775807).
diff --git a/test-suite/arithmetic/subcarryc.v b/test-suite/arithmetic/subcarryc.v
new file mode 100644
index 0000000000..e81b6536b2
--- /dev/null
+++ b/test-suite/arithmetic/subcarryc.v
@@ -0,0 +1,17 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : subcarryc 3 1 = C0 1).
+Check (eq_refl (C0 1) <: subcarryc 3 1 = C0 1).
+Check (eq_refl (C0 1) <<: subcarryc 3 1 = C0 1).
+Definition compute1 := Eval compute in subcarryc 3 1.
+Check (eq_refl compute1 : C0 1 = C0 1).
+
+Check (eq_refl : subcarryc 0 1 = C1 9223372036854775806).
+Check (eq_refl (C1 9223372036854775806) <: subcarryc 0 1 = C1 9223372036854775806).
+Check (eq_refl (C1 9223372036854775806) <<: subcarryc 0 1 = C1 9223372036854775806).
+Definition compute2 := Eval compute in subcarryc 0 1.
+Check (eq_refl compute2 : C1 9223372036854775806 = C1 9223372036854775806).
diff --git a/test-suite/arithmetic/tail0.v b/test-suite/arithmetic/tail0.v
new file mode 100644
index 0000000000..c9d426087a
--- /dev/null
+++ b/test-suite/arithmetic/tail0.v
@@ -0,0 +1,23 @@
+Require Import Int63.
+
+Set Implicit Arguments.
+
+Open Scope int63_scope.
+
+Check (eq_refl : tail0 2305843009213693952 = 61).
+Check (eq_refl 61 <: tail0 2305843009213693952 = 61).
+Check (eq_refl 61 <<: tail0 2305843009213693952 = 61).
+Definition compute1 := Eval compute in tail0 2305843009213693952.
+Check (eq_refl compute1 : 61 = 61).
+
+Check (eq_refl : tail0 1 = 0).
+Check (eq_refl 0 <: tail0 1 = 0).
+Check (eq_refl 0 <<: tail0 1 = 0).
+Definition compute2 := Eval compute in tail0 1.
+Check (eq_refl compute2 : 0 = 0).
+
+Check (eq_refl : tail0 0 = 63).
+Check (eq_refl 63 <: tail0 0 = 63).
+Check (eq_refl 63 <<: tail0 0 = 63).
+Definition compute3 := Eval compute in tail0 0.
+Check (eq_refl compute3 : 63 = 63).
diff --git a/test-suite/arithmetic/unsigned.v b/test-suite/arithmetic/unsigned.v
new file mode 100644
index 0000000000..82920bd201
--- /dev/null
+++ b/test-suite/arithmetic/unsigned.v
@@ -0,0 +1,18 @@
+(* This file checks that operations over int63 are unsigned. *)
+Require Import Int63.
+
+Open Scope int63_scope.
+
+(* (0-1) must be the maximum integer value and not negative 1 *)
+
+Check (eq_refl : 1/(0-1) = 0).
+Check (eq_refl 0 <: 1/(0-1) = 0).
+Check (eq_refl 0 <<: 1/(0-1) = 0).
+Definition compute1 := Eval compute in 1/(0-1).
+Check (eq_refl compute1 : 0 = 0).
+
+Check (eq_refl : 3 \% (0-1) = 3).
+Check (eq_refl 3 <: 3 \% (0-1) = 3).
+Check (eq_refl 3 <<: 3 \% (0-1) = 3).
+Definition compute2 := Eval compute in 3 \% (0-1).
+Check (eq_refl compute2 : 3 = 3).
diff --git a/test-suite/bugs/closed/HoTT_coq_056.v b/test-suite/bugs/closed/HoTT_coq_056.v
index 3e3a987a7c..b80e0bb0e4 100644
--- a/test-suite/bugs/closed/HoTT_coq_056.v
+++ b/test-suite/bugs/closed/HoTT_coq_056.v
@@ -94,9 +94,9 @@ Definition FunctorApplicationOf {C D} F {argsT} args {T} {rtn}
Global Arguments FunctorApplicationOf / {C} {D} F {argsT} args {T} {rtn} {_}.
Global Instance FunctorApplicationDash C D (F : Functor C D)
-: FunctorApplicationInterpretable F (IdentityFunctor C) F | 0.
+: FunctorApplicationInterpretable F (IdentityFunctor C) F | 0 := {}.
Global Instance FunctorApplicationFunctorFunctor' A B C C' D (F : Functor (A * B) D) (G : Functor C A) (H : Functor C' B)
-: FunctorApplicationInterpretable F (G, H) (F ∘ (FunctorProduct' G H))%functor | 100.
+: FunctorApplicationInterpretable F (G, H) (F ∘ (FunctorProduct' G H))%functor | 100 := {}.
Notation "F ⟨ x ⟩" := (FunctorApplicationOf F%functor x%functor) : functor_scope.
diff --git a/test-suite/bugs/closed/bug_3324.v b/test-suite/bugs/closed/bug_3324.v
index 45dbb57aa2..dae0d4c024 100644
--- a/test-suite/bugs/closed/bug_3324.v
+++ b/test-suite/bugs/closed/bug_3324.v
@@ -6,7 +6,7 @@ Module ETassi.
Record hProp := hp { hproptype :> Type ; isp : IsHProp hproptype}.
Record hSet := BuildhSet {setT:> Type; iss :> IsHSet setT}.
Canonical Structure default_HSet:= fun T P => (@BuildhSet T P).
- Global Instance isset_hProp : IsHSet hProp | 0.
+ Global Instance isset_hProp : IsHSet hProp | 0 := {}.
Check (eq_refl _ : setT (default_HSet _ _) = hProp).
Check (eq_refl _ : setT _ = hProp).
@@ -22,7 +22,7 @@ Module JGross.
Definition Unit_hp:hProp:=(hp Unit admit).
Record hSet := BuildhSet {setT:> Type; iss :> IsHSet setT}.
Canonical Structure default_HSet:= fun T P => (@BuildhSet T P).
- Global Instance isset_hProp : IsHSet hProp | 0.
+ Global Instance isset_hProp : IsHSet hProp | 0 := {}.
Definition isepi {X Y} `(f:X->Y) := forall Z: hSet,
forall g h: Y -> Z, (fun x => g (f x)) = (fun x => h (f x)) -> g = h.
Lemma isepi_issurj {X Y} (f:X->Y): isepi f -> True.
diff --git a/test-suite/bugs/closed/bug_3454.v b/test-suite/bugs/closed/bug_3454.v
index e4cd60cb24..0a01adec33 100644
--- a/test-suite/bugs/closed/bug_3454.v
+++ b/test-suite/bugs/closed/bug_3454.v
@@ -32,14 +32,14 @@ Local Instance isequiv_tgt_compose A B
: @IsEquiv (A -> {xy : B * B & fst xy = snd xy})
(A -> B)
(@compose A {xy : B * B & fst xy = snd xy} B
- (@compose {xy : B * B & fst xy = snd xy} _ B (@snd B B) pr1)).
+ (@compose {xy : B * B & fst xy = snd xy} _ B (@snd B B) pr1)) := {}.
(* Toplevel input, characters 220-223: *)
(* Error: Cannot infer this placeholder. *)
Local Instance isequiv_tgt_compose' A B
: @IsEquiv (A -> {xy : B * B & fst xy = snd xy})
(A -> B)
- (@compose A {xy : B * B & fst xy = snd xy} B (@compose {xy : B * B & fst xy = snd xy} _ B (@snd _ _) pr1)).
+ (@compose A {xy : B * B & fst xy = snd xy} B (@compose {xy : B * B & fst xy = snd xy} _ B (@snd _ _) pr1)) := {}.
(* Toplevel input, characters 221-232: *)
(* Error: *)
(* In environment *)
@@ -52,7 +52,7 @@ Local Instance isequiv_tgt_compose'' A B
: @IsEquiv (A -> {xy : B * B & fst xy = snd xy})
(A -> B)
(@compose A {xy : B * B & fst xy = snd xy} B (@compose {xy : B * B & fst xy = snd xy} _ B (@snd _ _)
- (fun s => s.(projT1)))).
+ (fun s => s.(projT1)))) := {}.
(* Toplevel input, characters 15-241:
Error:
Cannot infer an internal placeholder of type "Type" in environment:
diff --git a/test-suite/bugs/closed/bug_3682.v b/test-suite/bugs/closed/bug_3682.v
index 9d37d1a2d0..07b759afb5 100644
--- a/test-suite/bugs/closed/bug_3682.v
+++ b/test-suite/bugs/closed/bug_3682.v
@@ -1,6 +1,6 @@
Require Import TestSuite.admit.
Class Foo.
Definition bar `{Foo} (x : Set) := Set.
-Instance: Foo.
+Instance: Foo := {}.
Definition bar1 := bar nat.
Definition bar2 := bar ltac:(admit).
diff --git a/test-suite/bugs/closed/bug_4782.v b/test-suite/bugs/closed/bug_4782.v
index be17a96f15..c08195d502 100644
--- a/test-suite/bugs/closed/bug_4782.v
+++ b/test-suite/bugs/closed/bug_4782.v
@@ -15,8 +15,8 @@ Record T := { dom : Type }.
Definition pairT A B := {| dom := (dom A * dom B)%type |}.
Class C (A:Type).
Parameter B:T.
-Instance c (A:T) : C (dom A).
-Instance cn : C (dom B).
+Instance c (A:T) : C (dom A) := {}.
+Instance cn : C (dom B) := {}.
Parameter F : forall A:T, C (dom A) -> forall x:dom A, x=x -> A = A.
Set Typeclasses Debug.
Goal forall (A:T) (x:dom A), pairT A A = pairT A A.
diff --git a/test-suite/bugs/closed/bug_4798.v b/test-suite/bugs/closed/bug_4798.v
index 41a1251ca5..696812dee1 100644
--- a/test-suite/bugs/closed/bug_4798.v
+++ b/test-suite/bugs/closed/bug_4798.v
@@ -1,3 +1,5 @@
+(* DO NOT MODIFY THIS FILE DIRECTLY *)
+(* It is autogenerated by dev/tools/update-compat.py. *)
Check match 2 with 0 => 0 | S n => n end.
Notation "|" := 1 (compat "8.7").
Check match 2 with 0 => 0 | S n => n end. (* fails *)
diff --git a/test-suite/bugs/closed/bug_4836.v b/test-suite/bugs/closed/bug_4836.v
index 5838dcd8a7..9aefb10172 100644
--- a/test-suite/bugs/closed/bug_4836.v
+++ b/test-suite/bugs/closed/bug_4836.v
@@ -1 +1 @@
-(* -*- coq-prog-args: ("-compile" "bugs/closed/PLACEHOLDER.v") -*- *)
+(* -*- coq-prog-args: ("bugs/closed/PLACEHOLDER.v") -*- *)
diff --git a/test-suite/bugs/closed/bug_5401.v b/test-suite/bugs/closed/bug_5401.v
index 95193b993b..466e669d00 100644
--- a/test-suite/bugs/closed/bug_5401.v
+++ b/test-suite/bugs/closed/bug_5401.v
@@ -5,7 +5,7 @@ Parameter P : nat -> Type.
Parameter v : forall m, P m.
Parameter f : forall (P : nat -> Type), (forall a, P a) -> P 0.
Class U (R : P 0) (m : forall x, P x) : Prop.
-Instance w : U (f _ (fun _ => v _)) v.
+Instance w : U (f _ (fun _ => v _)) v := {}.
Print HintDb typeclass_instances.
End A.
diff --git a/test-suite/bugs/closed/bug_7811.v b/test-suite/bugs/closed/bug_7811.v
index fee330f22d..155f3285b7 100644
--- a/test-suite/bugs/closed/bug_7811.v
+++ b/test-suite/bugs/closed/bug_7811.v
@@ -1,4 +1,4 @@
-(* -*- mode: coq; coq-prog-args: ("-emacs" "-top" "atomic" "-Q" "." "iris" "-R" "." "stdpp") -*- *)
+(* -*- mode: coq; coq-prog-args: ("-top" "atomic" "-Q" "." "iris" "-R" "." "stdpp") -*- *)
(* File reduced by coq-bug-finder from original input, then from 140 lines to 26 lines, then from 141 lines to 27 lines, then from 142 lines to 27 lines, then from 272 lines to 61 lines, then from 291 lines to 94 lines, then from 678 lines to 142 lines, then from 418 lines to 161 lines, then from 538 lines to 189 lines, then from 840 lines to 493 lines, then from 751 lines to 567 lines, then from 913 lines to 649 lines, then from 875 lines to 666 lines, then from 784 lines to 568 lines, then from 655 lines to 173 lines, then from 317 lines to 94 lines, then from 172 lines to 86 lines, then from 102 lines to 86 lines, then from 130 lines to 86 lines, then from 332 lines to 112 lines, then from 279 lines to 111 lines, then from 3996 lines to 5697 lines, then from 153 lines to 117 lines, then from 146 lines to 108 lines, then from 124 lines to 108 lines *)
(* coqc version 8.8.0 (May 2018) compiled on May 2 2018 16:49:46 with OCaml 4.02.3
coqtop version 8.8.0 (May 2018) *)
diff --git a/test-suite/bugs/closed/bug_8076.v b/test-suite/bugs/closed/bug_8076.v
new file mode 100644
index 0000000000..7bee43620f
--- /dev/null
+++ b/test-suite/bugs/closed/bug_8076.v
@@ -0,0 +1,3 @@
+
+Notation leak a := ltac:(let x := constr:(Type) in exact a) (only parsing).
+Record foo@{} (P:leak Prop) := { f : leak Prop }.
diff --git a/test-suite/bugs/closed/bug_9166.v b/test-suite/bugs/closed/bug_9166.v
index 8a7e9c37b0..a89837dd12 100644
--- a/test-suite/bugs/closed/bug_9166.v
+++ b/test-suite/bugs/closed/bug_9166.v
@@ -1,3 +1,5 @@
+(* DO NOT MODIFY THIS FILE DIRECTLY *)
+(* It is autogenerated by dev/tools/update-compat.py. *)
Set Warnings "+deprecated".
Notation bar := option (compat "8.7").
diff --git a/test-suite/bugs/closed/bug_9268.v b/test-suite/bugs/closed/bug_9268.v
new file mode 100644
index 0000000000..02dd46f6d2
--- /dev/null
+++ b/test-suite/bugs/closed/bug_9268.v
@@ -0,0 +1,46 @@
+Require Import Coq.ZArith.ZArith.
+Require Import Coq.micromega.Lia.
+
+Local Open Scope Z_scope.
+
+Definition Register := Z%type.
+
+Definition Opcode := Z%type.
+
+Inductive InstructionI : Type
+ := Lb : Register -> Register -> Z -> InstructionI
+ | InvalidI : InstructionI.
+
+Inductive Instruction : Type
+ := IInstruction : InstructionI -> Instruction.
+
+Definition funct3_LB : Z := 0.
+
+Definition opcode_LOAD : Opcode := 3.
+
+Set Universe Polymorphism.
+
+Definition MachineInt := Z.
+
+Definition funct3_JALR := 0.
+
+Axiom InstructionMapper: Type -> Type.
+
+Definition apply_InstructionMapper(mapper: InstructionMapper Z)(inst: Instruction): Z :=
+ match inst with
+ | IInstruction InvalidI => 2
+ | IInstruction (Lb rd rs1 oimm12) => 3
+ end.
+
+Axiom Encoder: InstructionMapper MachineInt.
+
+Definition encode: Instruction -> MachineInt := apply_InstructionMapper Encoder.
+
+Lemma foo: forall (ins: InstructionI),
+ 0 <= encode (IInstruction ins) ->
+ 0 <= encode (IInstruction ins) .
+Proof.
+ Set Printing Universes.
+ intros.
+ lia.
+Qed.
diff --git a/test-suite/bugs/closed/bug_9367.v b/test-suite/bugs/closed/bug_9367.v
new file mode 100644
index 0000000000..885f6bc391
--- /dev/null
+++ b/test-suite/bugs/closed/bug_9367.v
@@ -0,0 +1,12 @@
+Section foo.
+Variable f : forall n : nat, nat.
+Arguments f {_}.
+Check f (n := 3).
+Global Arguments f {bar} : rename.
+End foo.
+
+Section foo.
+Variable f : forall n : nat, nat.
+Arguments f {_}.
+Fail Check f (bar := 3).
+End foo.
diff --git a/test-suite/bugs/closed/bug_9451.v b/test-suite/bugs/closed/bug_9451.v
new file mode 100644
index 0000000000..03bb0433f1
--- /dev/null
+++ b/test-suite/bugs/closed/bug_9451.v
@@ -0,0 +1,8 @@
+Goal False.
+cut True.
+assert False.
+evar (x : True).
+let v := open_constr:(_) in idtac. all: exfalso; clear.
+Optimize Proof.
+(* Error: Anomaly "grounding a non evar-free term" *)
+Abort All.
diff --git a/test-suite/bugs/closed/bug_9453.v b/test-suite/bugs/closed/bug_9453.v
new file mode 100644
index 0000000000..18745533b2
--- /dev/null
+++ b/test-suite/bugs/closed/bug_9453.v
@@ -0,0 +1,7 @@
+(* check compatibility with 8.8 and earlier for lack of warnings on the nat 5000 *)
+Set Warnings Append "+large-nat,+abstract-large-number".
+Fail Check 5001.
+Check 5000.
+(* Error:
+To avoid stack overflow, large numbers in nat are interpreted as applications of
+Nat.of_uint. *)
diff --git a/test-suite/complexity/constructor.v b/test-suite/complexity/constructor.v
index c5e1953829..31217ca75e 100644
--- a/test-suite/complexity/constructor.v
+++ b/test-suite/complexity/constructor.v
@@ -214,3 +214,4 @@ Fixpoint expand (n : nat) : Prop :=
Example Expand : expand 2500.
Time constructor. (* ~0.45 secs *)
+Qed.
diff --git a/test-suite/complexity/f_equal.v b/test-suite/complexity/f_equal.v
index 86698fa872..c2c566930b 100644
--- a/test-suite/complexity/f_equal.v
+++ b/test-suite/complexity/f_equal.v
@@ -12,3 +12,4 @@ end.
Goal stupid 23 = stupid 23.
Timeout 5 Time f_equal.
+Abort.
diff --git a/test-suite/complexity/injection.v b/test-suite/complexity/injection.v
index a76fa19d3c..298a07c1c4 100644
--- a/test-suite/complexity/injection.v
+++ b/test-suite/complexity/injection.v
@@ -111,3 +111,4 @@ Lemma test: forall n1 w1 n2 w2, mk_world n1 w1 = mk_world n2 w2 ->
Proof.
intros.
Timeout 10 Time injection H.
+Abort.
diff --git a/test-suite/complexity/ring.v b/test-suite/complexity/ring.v
index 51f7c4dabc..2d585ce5c5 100644
--- a/test-suite/complexity/ring.v
+++ b/test-suite/complexity/ring.v
@@ -5,3 +5,4 @@ Require Import ZArith.
Open Scope Z_scope.
Goal forall a, a+a+a+a+a+a+a+a+a+a+a+a+a = a*13.
Timeout 5 Time intro; ring.
+Abort.
diff --git a/test-suite/complexity/ring2.v b/test-suite/complexity/ring2.v
index 04fa59075b..1c119b8e42 100644
--- a/test-suite/complexity/ring2.v
+++ b/test-suite/complexity/ring2.v
@@ -50,3 +50,4 @@ Infix "+" := Zadd : Z_scope.
Goal forall a, a+a+a+a+a+a+a+a+a+a+a+a+a = a*13.
Timeout 5 Time intro; ring.
+Abort.
diff --git a/test-suite/complexity/setoid_rewrite.v b/test-suite/complexity/setoid_rewrite.v
index 2e3b006ef0..10b270ccad 100644
--- a/test-suite/complexity/setoid_rewrite.v
+++ b/test-suite/complexity/setoid_rewrite.v
@@ -8,3 +8,4 @@ Variable f : nat -> Prop.
Goal forall U:Prop, f 100 <-> U.
intros U.
Timeout 5 Time setoid_replace U with False.
+Abort.
diff --git a/test-suite/complexity/unification.v b/test-suite/complexity/unification.v
index d2ea527516..0c9915c84e 100644
--- a/test-suite/complexity/unification.v
+++ b/test-suite/complexity/unification.v
@@ -49,3 +49,4 @@ Goal
))))
.
Timeout 2 Time try refine (refl_equal _).
+Abort.
diff --git a/test-suite/coqchk/inductive_functor_squash.v b/test-suite/coqchk/inductive_functor_squash.v
new file mode 100644
index 0000000000..9d33fafc4c
--- /dev/null
+++ b/test-suite/coqchk/inductive_functor_squash.v
@@ -0,0 +1,15 @@
+
+
+Module Type T.
+ Parameter f : nat -> Type.
+End T.
+
+Module F(A:T).
+ Inductive ind : Prop :=
+ C : A.f 0 -> ind.
+End F.
+
+Module A. Definition f (x:nat) := True. End A.
+
+Module M := F A.
+(* M.ind could eliminate into Set/Type even though F.ind can't *)
diff --git a/test-suite/failure/int31.v b/test-suite/failure/int63.v
index ed4c9f9c78..0bb87c6548 100644
--- a/test-suite/failure/int31.v
+++ b/test-suite/failure/int63.v
@@ -1,17 +1,16 @@
-Require Import Int31 Cyclic31.
+Require Import Int63 Cyclic63.
-Open Scope int31_scope.
+Open Scope int63_scope.
(* This used to go through because of an unbalanced stack bug in the bytecode
interpreter *)
Lemma bad : False.
assert (1 = 2).
-change 1 with (add31 (addmuldiv31 65 (add31 1 1) 2) 1).
+change 1 with (Int63.add (Int63.addmuldiv 129 (Int63.add 1 1) 2) 1).
Fail vm_compute; reflexivity.
(*
discriminate.
Qed.
*)
Abort.
-
diff --git a/test-suite/ide/debug_ltac.fake b/test-suite/ide/debug_ltac.fake
new file mode 100644
index 0000000000..aa68fad39e
--- /dev/null
+++ b/test-suite/ide/debug_ltac.fake
@@ -0,0 +1,2 @@
+FAILADD { Debug On. }
+ADD { Set Debug On. }
diff --git a/test-suite/misc/4722.sh b/test-suite/misc/4722.sh
index 86bc50b5cd..70071b9d60 100755
--- a/test-suite/misc/4722.sh
+++ b/test-suite/misc/4722.sh
@@ -4,12 +4,12 @@ set -e
# create test files
mkdir -p misc/4722
ln -sf toto misc/4722/tata
-touch misc/4722.v
+touch misc/bug_4722.v
# run test
-$coqtop "-R" "misc/4722" "Foo" -top Top -load-vernac-source misc/4722.v
+$coqc "-R" "misc/4722" "Foo" -top Top misc/bug_4722.v
# clean up test files
rm misc/4722/tata
rmdir misc/4722
-rm misc/4722.v
+rm misc/bug_4722.v
diff --git a/test-suite/misc/7704.sh b/test-suite/misc/7704.sh
index 0ca2c97d24..5fc171649e 100755
--- a/test-suite/misc/7704.sh
+++ b/test-suite/misc/7704.sh
@@ -4,4 +4,4 @@ set -e
export PATH=$BIN:$PATH
-${coqtop#"$BIN"} -compile misc/aux7704.v
+${coqc#"$BIN"} misc/aux7704.v
diff --git a/test-suite/misc/aux7704.v b/test-suite/misc/aux7704.v
index 6fdcf67684..1c95211a71 100644
--- a/test-suite/misc/aux7704.v
+++ b/test-suite/misc/aux7704.v
@@ -1,4 +1,3 @@
-
Goal True /\ True.
Proof.
split.
diff --git a/test-suite/misc/deps-checksum.sh b/test-suite/misc/deps-checksum.sh
index a15a8fbee9..8523358303 100755
--- a/test-suite/misc/deps-checksum.sh
+++ b/test-suite/misc/deps-checksum.sh
@@ -3,4 +3,4 @@ rm -f misc/deps/A/*.vo misc/deps/B/*.vo
$coqc -R misc/deps/A A misc/deps/A/A.v
$coqc -R misc/deps/B A misc/deps/B/A.v
$coqc -R misc/deps/B A misc/deps/B/B.v
-$coqtop -R misc/deps/B A -R misc/deps/A A -load-vernac-source misc/deps/checksum.v
+$coqc -R misc/deps/B A -R misc/deps/A A misc/deps/checksum.v
diff --git a/test-suite/misc/deps-order.sh b/test-suite/misc/deps-order.sh
index 6bb2ba2da0..551515b0d6 100755
--- a/test-suite/misc/deps-order.sh
+++ b/test-suite/misc/deps-order.sh
@@ -10,12 +10,12 @@ R=$?
times
$coqc -R misc/deps/lib lib misc/deps/lib/foo.v 2>&1
$coqc -R misc/deps/lib lib -R misc/deps/client client misc/deps/client/foo.v 2>&1
-$coqtop -R misc/deps/lib lib -R misc/deps/client client -load-vernac-source misc/deps/client/bar.v 2>&1
+$coqc -R misc/deps/lib lib -R misc/deps/client client misc/deps/client/bar.v 2>&1
S=$?
if [ $R = 0 ] && [ $S = 0 ]; then
- printf "coqdep and coqtop agree\n"
+ printf "coqdep and coqc agree\n"
exit 0
else
- printf "coqdep and coqtop disagree\n"
+ printf "coqdep and coqc disagree\n"
exit 1
fi
diff --git a/test-suite/misc/deps-utf8.sh b/test-suite/misc/deps-utf8.sh
index acb45b2292..af69370ce4 100755
--- a/test-suite/misc/deps-utf8.sh
+++ b/test-suite/misc/deps-utf8.sh
@@ -8,7 +8,7 @@ rm -f misc/deps/théorèmes/*.v
tmpoutput=$(mktemp /tmp/coqcheck.XXXXXX)
$coqc -R misc/deps AlphaBêta misc/deps/αβ/γδ.v
R=$?
-$coqtop -R misc/deps AlphaBêta -load-vernac-source misc/deps/αβ/εζ.v
+$coqc -R misc/deps AlphaBêta misc/deps/αβ/εζ.v
S=$?
if [ $R = 0 ] && [ $S = 0 ]; then
exit 0
diff --git a/test-suite/misc/exitstatus.sh b/test-suite/misc/exitstatus.sh
index a327f4248b..afc415b2da 100755
--- a/test-suite/misc/exitstatus.sh
+++ b/test-suite/misc/exitstatus.sh
@@ -1,8 +1,5 @@
#!/bin/sh
-$coqtop -load-vernac-source misc/exitstatus/illtyped.v
-N=$?
$coqc misc/exitstatus/illtyped.v
P=$?
-printf "On ill-typed input, coqtop returned %s.\n" "$N"
printf "On ill-typed input, coqc returned %s.\n" "$P"
-if [ $N = 1 ] && [ $P = 1 ]; then exit 0; else exit 1; fi
+if [ $P = 1 ]; then exit 0; else exit 1; fi
diff --git a/test-suite/misc/universes/dune b/test-suite/misc/universes/dune
index 58bba300d2..0772f95604 100644
--- a/test-suite/misc/universes/dune
+++ b/test-suite/misc/universes/dune
@@ -5,4 +5,4 @@
(source_tree ../../../plugins))
(action
(with-outputs-to all_stdlib.v
- (run ./build_all_stdlib.sh))))
+ (bash "./build_all_stdlib.sh"))))
diff --git a/test-suite/output/Arguments_renaming.out b/test-suite/output/Arguments_renaming.out
index 583ea0cb43..ba4bc070c6 100644
--- a/test-suite/output/Arguments_renaming.out
+++ b/test-suite/output/Arguments_renaming.out
@@ -52,7 +52,6 @@ fix myplus (T : Type) (t : T) (n m : nat) {struct n} : nat :=
end
: forall T : Type, T -> nat -> nat -> nat
-myplus is not universe polymorphic
Arguments are renamed to Z, t, n, m
Argument Z is implicit and maximally inserted
Argument scopes are [type_scope _ nat_scope nat_scope]
@@ -92,7 +91,6 @@ fix myplus (T : Type) (t : T) (n m : nat) {struct n} : nat :=
end
: forall T : Type, T -> nat -> nat -> nat
-myplus is not universe polymorphic
Arguments are renamed to Z, t, n, m
Argument Z is implicit and maximally inserted
Argument scopes are [type_scope _ nat_scope nat_scope]
diff --git a/test-suite/output/Binder.out b/test-suite/output/Binder.out
index 6e27837b26..34558e9a6b 100644
--- a/test-suite/output/Binder.out
+++ b/test-suite/output/Binder.out
@@ -1,12 +1,8 @@
foo = fun '(x, y) => x + y
: nat * nat -> nat
-
-foo is not universe polymorphic
forall '(a, b), a /\ b
: Prop
foo = λ '(x, y), x + y
: nat * nat → nat
-
-foo is not universe polymorphic
∀ '(a, b), a ∧ b
: Prop
diff --git a/test-suite/output/Cases.out b/test-suite/output/Cases.out
index efcc299e82..cb835ab48d 100644
--- a/test-suite/output/Cases.out
+++ b/test-suite/output/Cases.out
@@ -7,7 +7,6 @@ fix F (t : t) : P t :=
: forall P : t -> Type,
(let x := t in forall x0 : x, P x0 -> P (k x0)) -> forall t : t, P t
-t_rect is not universe polymorphic
Argument scopes are [function_scope function_scope _]
= fun d : TT => match d with
| {| f3 := b |} => b
@@ -27,7 +26,6 @@ match Nat.eq_dec x y with
end
: forall (x y : nat) (P : nat -> Type), P x -> P y -> P y
-proj is not universe polymorphic
Argument scopes are [nat_scope nat_scope function_scope _ _]
foo =
fix foo (A : Type) (l : list A) {struct l} : option A :=
@@ -38,7 +36,6 @@ fix foo (A : Type) (l : list A) {struct l} : option A :=
end
: forall A : Type, list A -> option A
-foo is not universe polymorphic
Argument scopes are [type_scope list_scope]
uncast =
fun (A : Type) (x : I A) => match x with
@@ -46,12 +43,9 @@ fun (A : Type) (x : I A) => match x with
end
: forall A : Type, I A -> A
-uncast is not universe polymorphic
Argument scopes are [type_scope _]
foo' = if A 0 then true else false
: bool
-
-foo' is not universe polymorphic
f =
fun H : B =>
match H with
@@ -62,8 +56,6 @@ match H with
else fun _ : P false => Logic.I) x
end
: B -> True
-
-f is not universe polymorphic
The command has indeed failed with message:
Non exhaustive pattern-matching: no clause found for pattern
gadtTy _ _
@@ -86,19 +78,14 @@ The constructor D (in type J) expects 3 arguments.
lem1 =
fun dd : nat * nat => let (bb, cc) as aa return (aa = aa) := dd in eq_refl
: forall k : nat * nat, k = k
-
-lem1 is not universe polymorphic
lem2 =
fun dd : bool => if dd as aa return (aa = aa) then eq_refl else eq_refl
: forall k : bool, k = k
-lem2 is not universe polymorphic
Argument scope is [bool_scope]
lem3 =
fun dd : nat * nat => let (bb, cc) as aa return (aa = aa) := dd in eq_refl
: forall k : nat * nat, k = k
-
-lem3 is not universe polymorphic
1 subgoal
x : nat
diff --git a/test-suite/output/FunExt.v b/test-suite/output/FunExt.v
index 7658ce718e..440fe46003 100644
--- a/test-suite/output/FunExt.v
+++ b/test-suite/output/FunExt.v
@@ -1,3 +1,4 @@
+(* -*- coq-prog-args: ("-async-proofs" "no") -*- *)
Require Import FunctionalExtensionality.
(* Basic example *)
diff --git a/test-suite/output/Implicit.out b/test-suite/output/Implicit.out
index 0b0f501f9a..3b65003c29 100644
--- a/test-suite/output/Implicit.out
+++ b/test-suite/output/Implicit.out
@@ -5,7 +5,6 @@ ex_intro (P:=fun _ : nat => True) (x:=0) I
d2 = fun x : nat => d1 (y:=x)
: forall x x0 : nat, x0 = x -> x0 = x
-d2 is not universe polymorphic
Arguments x, x0 are implicit
Argument scopes are [nat_scope nat_scope _]
map id (1 :: nil)
diff --git a/test-suite/output/Int31Syntax.out b/test-suite/output/Int31Syntax.out
index 4e8796c14b..0d6504f5f8 100644
--- a/test-suite/output/Int31Syntax.out
+++ b/test-suite/output/Int31Syntax.out
@@ -12,3 +12,5 @@ I31
: int31
= 710436486
: int31
+The command has indeed failed with message:
+Cannot interpret this number as a value of type int31
diff --git a/test-suite/output/Int31Syntax.v b/test-suite/output/Int31Syntax.v
index 83be3b976b..48889a26ef 100644
--- a/test-suite/output/Int31Syntax.v
+++ b/test-suite/output/Int31Syntax.v
@@ -3,11 +3,12 @@ Require Import Int31 Cyclic31.
Open Scope int31_scope.
Check I31. (* Would be nice to have I31 : digits->digits->...->int31
For the moment, I31 : digits31 int31, which is better
- than (fix nfun .....) size int31 *)
+ than (fix nfun .....) size int31 *)
Check 2.
Check 1000000000000000000. (* = 660865024, after modulo 2^31 *)
Check (add31 2 2).
Check (2+2).
Eval vm_compute in 2+2.
Eval vm_compute in 65675757 * 565675998.
+Fail Check -1.
Close Scope int31_scope.
diff --git a/test-suite/output/Int63Syntax.out b/test-suite/output/Int63Syntax.out
new file mode 100644
index 0000000000..fdd5599565
--- /dev/null
+++ b/test-suite/output/Int63Syntax.out
@@ -0,0 +1,16 @@
+2
+ : int
+9223372036854775807
+ : int
+2 + 2
+ : int
+2 + 2
+ : int
+ = 4
+ : int
+ = 37151199385380486
+ : int
+The command has indeed failed with message:
+int63 are only non-negative numbers.
+The command has indeed failed with message:
+overflow in int63 literal: 9223372036854775808
diff --git a/test-suite/output/Int63Syntax.v b/test-suite/output/Int63Syntax.v
new file mode 100644
index 0000000000..3dc364eddb
--- /dev/null
+++ b/test-suite/output/Int63Syntax.v
@@ -0,0 +1,12 @@
+Require Import Int63 Cyclic63.
+
+Open Scope int63_scope.
+Check 2.
+Check 9223372036854775807.
+Check (Int63.add 2 2).
+Check (2+2).
+Eval vm_compute in 2+2.
+Eval vm_compute in 65675757 * 565675998.
+Fail Check -1.
+Fail Check 9223372036854775808.
+Close Scope int63_scope.
diff --git a/test-suite/output/Load.out b/test-suite/output/Load.out
index ebbd5d422b..0904d5540b 100644
--- a/test-suite/output/Load.out
+++ b/test-suite/output/Load.out
@@ -1,10 +1,6 @@
f = 2
: nat
-
-f is not universe polymorphic
u = I
: True
-
-u is not universe polymorphic
The command has indeed failed with message:
Files processed by Load cannot leave open proofs.
diff --git a/test-suite/output/Notations3.out b/test-suite/output/Notations3.out
index 71d92482d0..015dac2512 100644
--- a/test-suite/output/Notations3.out
+++ b/test-suite/output/Notations3.out
@@ -232,7 +232,6 @@ fun l : list nat => match l with
end
: list nat -> list nat
-foo is not universe polymorphic
Argument scope is [list_scope]
Notation
"'exists' x .. y , p" := ex (fun x => .. (ex (fun y => p)) ..) : type_scope
@@ -263,9 +262,5 @@ myfoo01 tt
: list (list nat)
amatch = mmatch 0 (with 0 => 1| 1 => 2 end)
: unit
-
-amatch is not universe polymorphic
alist = [0; 1; 2]
: list nat
-
-alist is not universe polymorphic
diff --git a/test-suite/output/Notations4.out b/test-suite/output/Notations4.out
index 94016e170b..efa895d709 100644
--- a/test-suite/output/Notations4.out
+++ b/test-suite/output/Notations4.out
@@ -45,5 +45,11 @@ fun x : nat => (x.-1)%pred
: Prop
##
: Prop
+myAnd1 True True
+ : Prop
+r 2 3
+ : Prop
Notation Cn := Foo.FooCn
-Expands to: Notation Top.J.Mfoo.Foo.Bar.Cn
+Expands to: Notation Notations4.J.Mfoo.Foo.Bar.Cn
+let v := 0%test17 in v : myint63
+ : myint63
diff --git a/test-suite/output/Notations4.v b/test-suite/output/Notations4.v
index 309115848f..b4c65ce196 100644
--- a/test-suite/output/Notations4.v
+++ b/test-suite/output/Notations4.v
@@ -165,6 +165,22 @@ Check ##.
End H.
+(* Fixing bugs reported by G. Gonthier in #9207 *)
+
+Module I.
+
+Definition myAnd A B := A /\ B.
+Notation myAnd1 A := (myAnd A).
+Check myAnd1 True True.
+
+Set Warnings "-auto-template".
+
+Record Pnat := {inPnat :> nat -> Prop}.
+Axiom r : nat -> Pnat.
+Check r 2 3.
+
+End I.
+
(* Fixing a bug reported by G. Gonthier in #9207 *)
Module J.
@@ -181,3 +197,16 @@ End Mfoo.
About Cn.
End J.
+
+Require Import Coq.Numbers.Cyclic.Int63.Int63.
+Module NumeralNotations.
+ Module Test17.
+ (** Test int63 *)
+ Declare Scope test17_scope.
+ Delimit Scope test17_scope with test17.
+ Local Set Primitive Projections.
+ Record myint63 := of_int { to_int : int }.
+ Numeral Notation myint63 of_int to_int : test17_scope.
+ Check let v := 0%test17 in v : myint63.
+ End Test17.
+End NumeralNotations.
diff --git a/test-suite/output/PatternsInBinders.out b/test-suite/output/PatternsInBinders.out
index bdbc5a5960..8a6d94c732 100644
--- a/test-suite/output/PatternsInBinders.out
+++ b/test-suite/output/PatternsInBinders.out
@@ -1,29 +1,20 @@
swap = fun '(x, y) => (y, x)
: A * B -> B * A
-
-swap is not universe polymorphic
fun '(x, y) => (y, x)
: A * B -> B * A
forall '(x, y), swap (x, y) = (y, x)
: Prop
proj_informative = fun '(exist _ x _) => x : A
: {x : A | P x} -> A
-
-proj_informative is not universe polymorphic
foo = fun '(Bar n b tt p) => if b then n + p else n - p
: Foo -> nat
-
-foo is not universe polymorphic
baz =
fun '(Bar n1 _ tt p1) '(Bar _ _ tt _) => n1 + p1
: Foo -> Foo -> nat
-
-baz is not universe polymorphic
swap =
fun (A B : Type) '(x, y) => (y, x)
: forall A B : Type, A * B -> B * A
-swap is not universe polymorphic
Arguments A, B are implicit and maximally inserted
Argument scopes are [type_scope type_scope _]
fun (A B : Type) '(x, y) => swap (x, y) = (y, x)
@@ -42,8 +33,6 @@ both_z =
fun pat : nat * nat =>
let '(n, p) as x := pat return (F x) in (Z n, Z p) : F (n, p)
: forall pat : nat * nat, F pat
-
-both_z is not universe polymorphic
fun '(x, y) '(z, t) => swap (x, y) = (z, t)
: A * B -> B * A -> Prop
forall '(x, y) '(z, t), swap (x, y) = (z, t)
@@ -53,7 +42,6 @@ fun (pat : nat) '(x, y) => x + y = pat
f = fun x : nat => x + x
: nat -> nat
-f is not universe polymorphic
Argument scope is [nat_scope]
fun x : nat => x + x
: nat -> nat
diff --git a/test-suite/output/PrintInfos.out b/test-suite/output/PrintInfos.out
index da1fca7134..ab4172711e 100644
--- a/test-suite/output/PrintInfos.out
+++ b/test-suite/output/PrintInfos.out
@@ -46,7 +46,6 @@ fix add (n m : nat) {struct n} : nat :=
end
: nat -> nat -> nat
-Nat.add is not universe polymorphic
Argument scopes are [nat_scope nat_scope]
Nat.add : nat -> nat -> nat
@@ -86,7 +85,6 @@ Argument x is implicit and maximally inserted
Expands to: Constant PrintInfos.bar
*** [ bar : foo ]
-bar is not universe polymorphic
Expanded type for implicit arguments
bar : forall x : nat, x = 0
diff --git a/test-suite/output/RecognizePluginWarning.v b/test-suite/output/RecognizePluginWarning.v
index cd667bbd00..a53b52396f 100644
--- a/test-suite/output/RecognizePluginWarning.v
+++ b/test-suite/output/RecognizePluginWarning.v
@@ -1,4 +1,4 @@
-(* -*- mode: coq; coq-prog-args: ("-emacs" "-w" "extraction-logical-axiom") -*- *)
+(* -*- mode: coq; coq-prog-args: ("-w" "extraction-logical-axiom") -*- *)
(* Test that mentioning a warning defined in plugins works. The failure
mode here is that these result in a warning about unknown warnings, since the
diff --git a/test-suite/output/Show.v b/test-suite/output/Show.v
index 60faac8dd9..c875051bdc 100644
--- a/test-suite/output/Show.v
+++ b/test-suite/output/Show.v
@@ -5,7 +5,7 @@
Theorem nums : forall (n m : nat), n = m -> (S n) = (S m).
Proof.
intros.
- induction n as [| n'].
+ induction n as [| n'].
induction m as [| m'].
Show.
Admitted.
diff --git a/test-suite/output/StringSyntax.out b/test-suite/output/StringSyntax.out
index c7e6ef950e..9366113c0c 100644
--- a/test-suite/output/StringSyntax.out
+++ b/test-suite/output/StringSyntax.out
@@ -433,7 +433,6 @@ end
P "167" ->
P "168" -> P "169" -> P "170" -> P "171" -> P "172" -> P "173" -> P "174" -> P "175" -> P "176" -> P "177" -> P "178" -> P "179" -> P "180" -> P "181" -> P "182" -> P "183" -> P "184" -> P "185" -> P "186" -> P "187" -> P "188" -> P "189" -> P "190" -> P "191" -> P "192" -> P "193" -> P "194" -> P "195" -> P "196" -> P "197" -> P "198" -> P "199" -> P "200" -> P "201" -> P "202" -> P "203" -> P "204" -> P "205" -> P "206" -> P "207" -> P "208" -> P "209" -> P "210" -> P "211" -> P "212" -> P "213" -> P "214" -> P "215" -> P "216" -> P "217" -> P "218" -> P "219" -> P "220" -> P "221" -> P "222" -> P "223" -> P "224" -> P "225" -> P "226" -> P "227" -> P "228" -> P "229" -> P "230" -> P "231" -> P "232" -> P "233" -> P "234" -> P "235" -> P "236" -> P "237" -> P "238" -> P "239" -> P "240" -> P "241" -> P "242" -> P "243" -> P "244" -> P "245" -> P "246" -> P "247" -> P "248" -> P "249" -> P "250" -> P "251" -> P "252" -> P "253" -> P "254" -> P "255" -> forall b : byte, P b
-byte_rect is not universe polymorphic
Argument scopes are [function_scope _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ byte_scope]
byte_rec =
fun P : byte -> Set => byte_rect P
@@ -608,7 +607,6 @@ fun P : byte -> Set => byte_rect P
P "167" ->
P "168" -> P "169" -> P "170" -> P "171" -> P "172" -> P "173" -> P "174" -> P "175" -> P "176" -> P "177" -> P "178" -> P "179" -> P "180" -> P "181" -> P "182" -> P "183" -> P "184" -> P "185" -> P "186" -> P "187" -> P "188" -> P "189" -> P "190" -> P "191" -> P "192" -> P "193" -> P "194" -> P "195" -> P "196" -> P "197" -> P "198" -> P "199" -> P "200" -> P "201" -> P "202" -> P "203" -> P "204" -> P "205" -> P "206" -> P "207" -> P "208" -> P "209" -> P "210" -> P "211" -> P "212" -> P "213" -> P "214" -> P "215" -> P "216" -> P "217" -> P "218" -> P "219" -> P "220" -> P "221" -> P "222" -> P "223" -> P "224" -> P "225" -> P "226" -> P "227" -> P "228" -> P "229" -> P "230" -> P "231" -> P "232" -> P "233" -> P "234" -> P "235" -> P "236" -> P "237" -> P "238" -> P "239" -> P "240" -> P "241" -> P "242" -> P "243" -> P "244" -> P "245" -> P "246" -> P "247" -> P "248" -> P "249" -> P "250" -> P "251" -> P "252" -> P "253" -> P "254" -> P "255" -> forall b : byte, P b
-byte_rec is not universe polymorphic
Argument scopes are [function_scope _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ byte_scope]
byte_ind =
fun (P : byte -> Prop) (f : P "000") (f0 : P "001") (f1 : P "002") (f2 : P "003") (f3 : P "004") (f4 : P "005") (f5 : P "006") (f6 : P "007") (f7 : P "008") (f8 : P "009") (f9 : P "010") (f10 : P "011") (f11 : P "012") (f12 : P "013") (f13 : P "014") (f14 : P "015") (f15 : P "016") (f16 : P "017") (f17 : P "018") (f18 : P "019") (f19 : P "020") (f20 : P "021") (f21 : P "022") (f22 : P "023") (f23 : P "024") (f24 : P "025") (f25 : P "026") (f26 : P "027") (f27 : P "028") (f28 : P "029") (f29 : P "030") (f30 : P "031") (f31 : P " ") (f32 : P "!") (f33 : P """") (f34 : P "#") (f35 : P "$") (f36 : P "%") (f37 : P "&") (f38 : P "'") (f39 : P "(") (f40 : P ")") (f41 : P "*") (f42 : P "+") (f43 : P ",") (f44 : P "-") (f45 : P ".") (f46 : P "/") (f47 : P "0") (f48 : P "1") (f49 : P "2") (f50 : P "3") (f51 : P "4") (f52 : P "5") (f53 : P "6") (f54 : P "7") (f55 : P "8") (f56 : P "9") (f57 : P ":") (f58 : P ";") (f59 : P "<") (f60 : P "=") (f61 : P ">") (f62 : P "?")
@@ -1045,7 +1043,6 @@ end
P "167" ->
P "168" -> P "169" -> P "170" -> P "171" -> P "172" -> P "173" -> P "174" -> P "175" -> P "176" -> P "177" -> P "178" -> P "179" -> P "180" -> P "181" -> P "182" -> P "183" -> P "184" -> P "185" -> P "186" -> P "187" -> P "188" -> P "189" -> P "190" -> P "191" -> P "192" -> P "193" -> P "194" -> P "195" -> P "196" -> P "197" -> P "198" -> P "199" -> P "200" -> P "201" -> P "202" -> P "203" -> P "204" -> P "205" -> P "206" -> P "207" -> P "208" -> P "209" -> P "210" -> P "211" -> P "212" -> P "213" -> P "214" -> P "215" -> P "216" -> P "217" -> P "218" -> P "219" -> P "220" -> P "221" -> P "222" -> P "223" -> P "224" -> P "225" -> P "226" -> P "227" -> P "228" -> P "229" -> P "230" -> P "231" -> P "232" -> P "233" -> P "234" -> P "235" -> P "236" -> P "237" -> P "238" -> P "239" -> P "240" -> P "241" -> P "242" -> P "243" -> P "244" -> P "245" -> P "246" -> P "247" -> P "248" -> P "249" -> P "250" -> P "251" -> P "252" -> P "253" -> P "254" -> P "255" -> forall b : byte, P b
-byte_ind is not universe polymorphic
Argument scopes are [function_scope _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ byte_scope]
"000"
: byte
diff --git a/test-suite/output/TranspModtype.out b/test-suite/output/TranspModtype.out
index 67b65d4b81..f94ed64234 100644
--- a/test-suite/output/TranspModtype.out
+++ b/test-suite/output/TranspModtype.out
@@ -1,15 +1,7 @@
TrM.A = M.A
: Set
-
-TrM.A is not universe polymorphic
OpM.A = M.A
: Set
-
-OpM.A is not universe polymorphic
TrM.B = M.B
: Set
-
-TrM.B is not universe polymorphic
*** [ OpM.B : Set ]
-
-OpM.B is not universe polymorphic
diff --git a/test-suite/output/UnclosedBlocks.v b/test-suite/output/UnclosedBlocks.v
index 854bd6a6d5..b9ba579246 100644
--- a/test-suite/output/UnclosedBlocks.v
+++ b/test-suite/output/UnclosedBlocks.v
@@ -1,4 +1,3 @@
-(* -*- mode: coq; coq-prog-args: ("-compile" "UnclosedBlocks.v") *)
Module Foo.
Module Closed.
End Closed.
diff --git a/test-suite/output/UnivBinders.out b/test-suite/output/UnivBinders.out
index 0bd6ade690..a960fe3441 100644
--- a/test-suite/output/UnivBinders.out
+++ b/test-suite/output/UnivBinders.out
@@ -9,7 +9,6 @@ fun (A : Type@{u}) (p : PWrap@{u} A) => punwrap _ p
: forall A : Type@{u}, PWrap@{u} A -> A
(* u |= *)
-punwrap is universe polymorphic
Argument scopes are [type_scope _]
Record RWrap (A : Type@{u}) : Type@{u} := rwrap { runwrap : A }
@@ -20,33 +19,26 @@ fun (A : Type@{u}) (r : RWrap@{u} A) => let (runwrap) := r in runwrap
: forall A : Type@{u}, RWrap@{u} A -> A
(* u |= *)
-runwrap is universe polymorphic
Argument scopes are [type_scope _]
Wrap@{u} = fun A : Type@{u} => A
: Type@{u} -> Type@{u}
(* u |= *)
-Wrap is universe polymorphic
Argument scope is [type_scope]
wrap@{u} =
fun (A : Type@{u}) (Wrap : Wrap@{u} A) => Wrap
: forall A : Type@{u}, Wrap@{u} A -> A
(* u |= *)
-wrap is universe polymorphic
Arguments A, Wrap are implicit and maximally inserted
Argument scopes are [type_scope _]
bar@{u} = nat
: Wrap@{u} Set
(* u |= Set < u *)
-
-bar is universe polymorphic
foo@{u UnivBinders.17 v} =
Type@{UnivBinders.17} -> Type@{v} -> Type@{u}
: Type@{max(u+1,UnivBinders.17+1,v+1)}
(* u UnivBinders.17 v |= *)
-
-foo is universe polymorphic
Type@{i} -> Type@{j}
: Type@{max(i+1,j+1)}
(* {j i} |= *)
@@ -56,8 +48,6 @@ Type@{i} -> Type@{j}
mono = Type@{mono.u}
: Type@{mono.u+1}
(* {mono.u} |= *)
-
-mono is not universe polymorphic
mono
: Type@{mono.u+1}
Type@{mono.u}
@@ -78,22 +68,16 @@ bobmorane =
let tt := Type@{UnivBinders.32} in
let ff := Type@{UnivBinders.34} in tt -> ff
: Type@{max(UnivBinders.31,UnivBinders.33)}
-
-bobmorane is not universe polymorphic
The command has indeed failed with message:
Universe u already bound.
foo@{E M N} =
Type@{M} -> Type@{N} -> Type@{E}
: Type@{max(E+1,M+1,N+1)}
(* E M N |= *)
-
-foo is universe polymorphic
foo@{u UnivBinders.17 v} =
Type@{UnivBinders.17} -> Type@{v} -> Type@{u}
: Type@{max(u+1,UnivBinders.17+1,v+1)}
(* u UnivBinders.17 v |= *)
-
-foo is universe polymorphic
Inductive Empty@{E} : Type@{E} :=
Record PWrap (A : Type@{E}) : Type@{E} := pwrap { punwrap : A }
@@ -119,26 +103,18 @@ bind_univs.mono =
Type@{bind_univs.mono.u}
: Type@{bind_univs.mono.u+1}
(* {bind_univs.mono.u} |= *)
-
-bind_univs.mono is not universe polymorphic
bind_univs.poly@{u} = Type@{u}
: Type@{u+1}
(* u |= *)
-
-bind_univs.poly is universe polymorphic
insec@{v} = Type@{u} -> Type@{v}
: Type@{max(u+1,v+1)}
(* v |= *)
-
-insec is universe polymorphic
Inductive insecind@{k} : Type@{k+1} := inseccstr : Type@{k} -> insecind@{k}
For inseccstr: Argument scope is [type_scope]
insec@{u v} = Type@{u} -> Type@{v}
: Type@{max(u+1,v+1)}
(* u v |= *)
-
-insec is universe polymorphic
Inductive insecind@{u k} : Type@{k+1} :=
inseccstr : Type@{k} -> insecind@{u k}
@@ -146,29 +122,19 @@ For inseccstr: Argument scope is [type_scope]
insec2@{u} = Prop
: Type@{Set+1}
(* u |= *)
-
-insec2 is universe polymorphic
inmod@{u} = Type@{u}
: Type@{u+1}
(* u |= *)
-
-inmod is universe polymorphic
SomeMod.inmod@{u} = Type@{u}
: Type@{u+1}
(* u |= *)
-
-SomeMod.inmod is universe polymorphic
inmod@{u} = Type@{u}
: Type@{u+1}
(* u |= *)
-
-inmod is universe polymorphic
Applied.infunct@{u v} =
inmod@{u} -> Type@{v}
: Type@{max(u+1,v+1)}
(* u v |= *)
-
-Applied.infunct is universe polymorphic
axfoo@{i UnivBinders.56 UnivBinders.57} :
Type@{UnivBinders.56} -> Type@{i}
(* i UnivBinders.56 UnivBinders.57 |= *)
diff --git a/test-suite/output/UsePluginWarning.v b/test-suite/output/UsePluginWarning.v
index c6e0054641..618b8fd42f 100644
--- a/test-suite/output/UsePluginWarning.v
+++ b/test-suite/output/UsePluginWarning.v
@@ -1,5 +1,4 @@
-(* -*- mode: coq; coq-prog-args: ("-emacs" "-w" "-extraction-logical-axiom") -*- *)
-
+(* -*- mode: coq; coq-prog-args: ("-w" "-extraction-logical-axiom") -*- *)
Require Extraction.
Axiom foo : Prop.
diff --git a/test-suite/output/goal_output.out b/test-suite/output/goal_output.out
index 20568f742a..773533a8d3 100644
--- a/test-suite/output/goal_output.out
+++ b/test-suite/output/goal_output.out
@@ -1,11 +1,7 @@
Nat.t = nat
: Set
-
-Nat.t is not universe polymorphic
Nat.t = nat
: Set
-
-Nat.t is not universe polymorphic
1 subgoal
============================
diff --git a/test-suite/output/inference.out b/test-suite/output/inference.out
index f545ca679c..f7ffd1959a 100644
--- a/test-suite/output/inference.out
+++ b/test-suite/output/inference.out
@@ -4,8 +4,6 @@ fun e : option L => match e with
| None => None
end
: option L -> option L
-
-P is not universe polymorphic
fun n : nat => let y : T n := A n in ?t ?x : T n
: forall n : nat, T n
where
diff --git a/test-suite/output/simpl.v b/test-suite/output/simpl.v
index 5f1926f142..5f7e3ab9dd 100644
--- a/test-suite/output/simpl.v
+++ b/test-suite/output/simpl.v
@@ -11,3 +11,4 @@ Undo.
simpl (0 + _).
Show.
Undo.
+Abort.
diff --git a/test-suite/output/sint63Notation.out b/test-suite/output/sint63Notation.out
new file mode 100644
index 0000000000..9d325b38c7
--- /dev/null
+++ b/test-suite/output/sint63Notation.out
@@ -0,0 +1,24 @@
+ = 0
+ : uint
+ = 1
+ : uint
+ = 9223372036854775807
+ : uint
+let v := 0 in v : uint
+ : uint
+let v := 1 in v : uint
+ : uint
+let v := 9223372036854775807 in v : uint
+ : uint
+ = 0
+ : sint
+ = 1
+ : sint
+ = -1
+ : sint
+let v := 0 in v : sint
+ : sint
+let v := 1 in v : sint
+ : sint
+let v := -1 in v : sint
+ : sint
diff --git a/test-suite/output/sint63Notation.v b/test-suite/output/sint63Notation.v
new file mode 100644
index 0000000000..331d74ed3d
--- /dev/null
+++ b/test-suite/output/sint63Notation.v
@@ -0,0 +1,37 @@
+From Coq
+Require Import Int63.
+Import ZArith.
+
+Declare Scope uint_scope.
+Declare Scope sint_scope.
+Delimit Scope uint_scope with uint.
+Delimit Scope sint_scope with sint.
+
+Record uint := wrapu { unwrapu : int }.
+Record sint := wraps { unwraps : int }.
+
+Definition uof_Z (v : Z) := wrapu (of_Z v).
+Definition uto_Z (v : uint) := to_Z (unwrapu v).
+
+Definition sof_Z (v : Z) := wraps (of_Z (v mod (2 ^ 31))).
+Definition as_signed (bw : Z) (v : Z) :=
+ (((2 ^ (bw - 1) + v) mod (2 ^ bw)) - 2 ^ (bw - 1))%Z.
+
+Definition sto_Z (v : sint) := as_signed 31 (to_Z (unwraps v)).
+Numeral Notation uint uof_Z uto_Z : uint_scope.
+Numeral Notation sint sof_Z sto_Z : sint_scope.
+Open Scope uint_scope.
+Compute uof_Z 0.
+Compute uof_Z 1.
+Compute uof_Z (-1).
+Check let v := 0 in v : uint.
+Check let v := 1 in v : uint.
+Check let v := -1 in v : uint.
+Close Scope uint_scope.
+Open Scope sint_scope.
+Compute sof_Z 0.
+Compute sof_Z 1.
+Compute sof_Z (-1).
+Check let v := 0 in v : sint.
+Check let v := 1 in v : sint.
+Check let v := -1 in v : sint.
diff --git a/test-suite/output/unifconstraints.v b/test-suite/output/unifconstraints.v
index 179dec3fb0..c987d66c5f 100644
--- a/test-suite/output/unifconstraints.v
+++ b/test-suite/output/unifconstraints.v
@@ -1,3 +1,4 @@
+(* -*- coq-prog-args: ("-async-proofs" "no") -*- *)
(* Set Printing Existential Instances. *)
Unset Solve Unification Constraints.
Axiom veeryyyyyyyyyyyyloooooooooooooonggidentifier : nat.
diff --git a/test-suite/report.sh b/test-suite/report.sh
index cef615266b..71aac029ea 100755
--- a/test-suite/report.sh
+++ b/test-suite/report.sh
@@ -24,21 +24,11 @@ cp summary.log "$SAVEDIR"/
rm "$FAILED"
# print info
-if [ -n "$TRAVIS" ] || [ -n "$APPVEYOR" ] || [ -n "$PRINT_LOGS" ]; then
+if [ -n "$APPVEYOR" ] || [ -n "$PRINT_LOGS" ]; then
find logs/ -name '*.log' -not -name 'summary.log' -print0 | while IFS= read -r -d '' file; do
- if [ -n "$TRAVIS" ]; then
- # ${foo////.} replaces every / by . in $foo
- printf 'travis_fold:start:coq.logs.%s\n' "${file////.}";
- else printf '%s\n' "$file"
- fi
-
+ printf '%s\n' "$file"
cat "$file"
-
- if [ -n "$TRAVIS" ]; then
- # ${foo////.} replaces every / by . in $foo
- printf 'travis_fold:end:coq.logs.%s\n' "${file////.}";
- else printf '\n'
- fi
+ printf '\n'
done
printed_logs=1
fi
diff --git a/test-suite/ssr/ipat_replace.v b/test-suite/ssr/ipat_replace.v
new file mode 100644
index 0000000000..528f33f30d
--- /dev/null
+++ b/test-suite/ssr/ipat_replace.v
@@ -0,0 +1,17 @@
+Require Import ssreflect.
+
+Lemma test : True.
+Proof.
+have H : True.
+ by [].
+have {}H : True.
+ by apply: H.
+by apply: H.
+Qed.
+
+Lemma test2 (H : True) : False -> False -> False.
+Proof.
+move=> {}W.
+move=> {}H.
+by apply: H.
+Qed.
diff --git a/test-suite/success/Compat88.v b/test-suite/success/Compat88.v
index e2045900d5..1233a4b8f5 100644
--- a/test-suite/success/Compat88.v
+++ b/test-suite/success/Compat88.v
@@ -4,7 +4,7 @@
Require Coq.Strings.Ascii Coq.Strings.String.
Require Coq.ZArith.BinIntDef Coq.PArith.BinPosDef Coq.NArith.BinNatDef.
Require Coq.Reals.Rdefinitions.
-Require Coq.Numbers.Cyclic.Int31.Cyclic31.
+Require Coq.Numbers.Cyclic.Int63.Cyclic63.
Require Import Coq.Compat.Coq88. (* XXX FIXME Should not need [Require], see https://github.com/coq/coq/issues/8311 *)
@@ -15,4 +15,4 @@ Check BinNat.N.eqb 1 1.
Check BinInt.Z.eqb 1 1.
Check BinPos.Pos.eqb 1 1.
Check Rdefinitions.Rplus 1 1.
-Check Int31.iszero 1.
+Check Int63.is_zero 1.
diff --git a/test-suite/success/CompatCurrentFlag.v b/test-suite/success/CompatCurrentFlag.v
index 5650dba236..81469d79c3 100644
--- a/test-suite/success/CompatCurrentFlag.v
+++ b/test-suite/success/CompatCurrentFlag.v
@@ -1,3 +1,3 @@
-(* -*- coq-prog-args: ("-compat" "8.9") -*- *)
+(* -*- coq-prog-args: ("-compat" "8.10") -*- *)
(** Check that the current compatibility flag actually requires the relevant modules. *)
-Import Coq.Compat.Coq89.
+Import Coq.Compat.Coq810.
diff --git a/test-suite/success/CompatOldFlag.v b/test-suite/success/CompatOldFlag.v
index 37d50ee67d..afeb57f9f2 100644
--- a/test-suite/success/CompatOldFlag.v
+++ b/test-suite/success/CompatOldFlag.v
@@ -1,5 +1,5 @@
-(* -*- coq-prog-args: ("-compat" "8.7") -*- *)
+(* -*- coq-prog-args: ("-compat" "8.8") -*- *)
(** Check that the current-minus-two compatibility flag actually requires the relevant modules. *)
+Import Coq.Compat.Coq810.
Import Coq.Compat.Coq89.
Import Coq.Compat.Coq88.
-Import Coq.Compat.Coq87.
diff --git a/test-suite/success/CompatOldOldFlag.v b/test-suite/success/CompatOldOldFlag.v
new file mode 100644
index 0000000000..1f62635f50
--- /dev/null
+++ b/test-suite/success/CompatOldOldFlag.v
@@ -0,0 +1,6 @@
+(* -*- coq-prog-args: ("-compat" "8.7") -*- *)
+(** Check that the current-minus-three compatibility flag actually requires the relevant modules. *)
+Import Coq.Compat.Coq810.
+Import Coq.Compat.Coq89.
+Import Coq.Compat.Coq88.
+Import Coq.Compat.Coq87.
diff --git a/test-suite/success/CompatPreviousFlag.v b/test-suite/success/CompatPreviousFlag.v
index 9981388381..c8f75915c8 100644
--- a/test-suite/success/CompatPreviousFlag.v
+++ b/test-suite/success/CompatPreviousFlag.v
@@ -1,4 +1,4 @@
-(* -*- coq-prog-args: ("-compat" "8.8") -*- *)
+(* -*- coq-prog-args: ("-compat" "8.9") -*- *)
(** Check that the current-minus-one compatibility flag actually requires the relevant modules. *)
+Import Coq.Compat.Coq810.
Import Coq.Compat.Coq89.
-Import Coq.Compat.Coq88.
diff --git a/test-suite/success/Nia.v b/test-suite/success/Nia.v
new file mode 100644
index 0000000000..62ecece792
--- /dev/null
+++ b/test-suite/success/Nia.v
@@ -0,0 +1,918 @@
+Require Import Coq.ZArith.ZArith.
+Require Import Coq.micromega.Lia.
+Open Scope Z_scope.
+
+(** Add [Z.to_euclidean_division_equations] to the end of [zify], just for this
+ file. *)
+Ltac zify ::= repeat (zify_nat; zify_positive; zify_N); zify_op; Z.to_euclidean_division_equations.
+
+Lemma Z_zerop_or x : x = 0 \/ x <> 0. Proof. nia. Qed.
+Lemma Z_eq_dec_or (x y : Z) : x = y \/ x <> y. Proof. nia. Qed.
+
+Ltac unique_pose_proof pf :=
+ let T := type of pf in
+ lazymatch goal with
+ | [ H : T |- _ ] => fail
+ | _ => pose proof pf
+ end.
+
+Ltac saturate_mod_div :=
+ repeat match goal with
+ | [ |- context[?x mod ?y] ] => unique_pose_proof (Z_zerop_or (x / y))
+ | [ H : context[?x mod ?y] |- _ ] => unique_pose_proof (Z_zerop_or (x / y))
+ | [ |- context[?x / ?y] ] => unique_pose_proof (Z_zerop_or y)
+ | [ H : context[?x / ?y] |- _ ] => unique_pose_proof (Z_zerop_or y)
+ | [ |- context[Z.rem ?x ?y] ] => unique_pose_proof (Z_zerop_or (Z.quot x y))
+ | [ H : context[Z.rem ?x ?y] |- _ ] => unique_pose_proof (Z_zerop_or (Z.quot x y))
+ | [ |- context[Z.quot ?x ?y] ] => unique_pose_proof (Z_zerop_or y)
+ | [ H : context[Z.quot ?x ?y] |- _ ] => unique_pose_proof (Z_zerop_or y)
+ end.
+
+Ltac t := intros; saturate_mod_div; try nia.
+
+Ltac destr_step :=
+ match goal with
+ | [ H : and _ _ |- _ ] => destruct H
+ | [ H : or _ _ |- _ ] => destruct H
+ end.
+
+Example mod_0_l: forall x : Z, 0 mod x = 0. Proof. t. Qed.
+Example mod_0_r: forall x : Z, x mod 0 = 0. Proof. intros; nia. Qed.
+Example Z_mod_same_full: forall a : Z, a mod a = 0. Proof. t. Qed.
+Example Zmod_0_l: forall a : Z, 0 mod a = 0. Proof. t. Qed.
+Example Zmod_0_r: forall a : Z, a mod 0 = 0. Proof. intros; nia. Qed.
+Example mod_mod_same: forall x y : Z, (x mod y) mod y = x mod y. Proof. t. Qed.
+Example Zmod_mod: forall a n : Z, (a mod n) mod n = a mod n. Proof. t. Qed.
+Example Zmod_1_r: forall a : Z, a mod 1 = 0. Proof. intros; nia. Qed.
+Example Zmod_div: forall a b : Z, a mod b / b = 0. Proof. intros; nia. Qed.
+Example Z_mod_1_r: forall a : Z, a mod 1 = 0. Proof. intros; nia. Qed.
+Example Z_mod_same: forall a : Z, a > 0 -> a mod a = 0. Proof. t. Qed.
+Example Z_mod_mult: forall a b : Z, (a * b) mod b = 0.
+Proof.
+ intros a b.
+ assert (b = 0 \/ (a * b) / b = a) by nia.
+ nia.
+Qed.
+Example Z_mod_same': forall a : Z, a <> 0 -> a mod a = 0. Proof. t. Qed.
+Example Z_mod_0_l: forall a : Z, a <> 0 -> 0 mod a = 0. Proof. t. Qed.
+Example Zmod_opp_opp: forall a b : Z, - a mod - b = - (a mod b).
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or ((-a)/(-b)) (a/b)).
+ nia.
+Qed.
+Example Z_mod_le: forall a b : Z, 0 <= a -> 0 < b -> a mod b <= a. Proof. t. Qed.
+Example Zmod_le: forall a b : Z, 0 < b -> 0 <= a -> a mod b <= a. Proof. t. Qed.
+Example Zplus_mod_idemp_r: forall a b n : Z, (b + a mod n) mod n = (b + a) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((b + a mod n) / n = (b / n) + (b mod n + a mod n) / n)
+ by nia.
+ assert ((b + a) / n = (b / n) + (a / n) + (b mod n + a mod n) / n)
+ by nia.
+ nia.
+Qed.
+Example Zplus_mod_idemp_l: forall a b n : Z, (a mod n + b) mod n = (a + b) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((a mod n + b) / n = (b / n) + (b mod n + a mod n) / n) by nia.
+ assert ((a + b) / n = (b / n) + (a / n) + (b mod n + a mod n) / n) by nia.
+ nia.
+Qed.
+Example Zmult_mod_distr_r: forall a b c : Z, (a * c) mod (b * c) = a mod b * c.
+Proof.
+ intros a b c.
+ destruct (Z_zerop c); try nia.
+ pose proof (Z_eq_dec_or ((a * c) / (b * c)) (a / b)).
+ nia.
+Qed.
+Example Z_mod_zero_opp_full: forall a b : Z, a mod b = 0 -> - a mod b = 0.
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or (a/b) (-(-a/b))).
+ nia.
+Qed.
+Example Zmult_mod_idemp_r: forall a b n : Z, (b * (a mod n)) mod n = (b * a) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((b * (a mod n)) / n = (b / n) * (a mod n) + ((b mod n) * (a mod n)) / n)
+ by nia.
+ assert ((b * a) / n = (b / n) * (a / n) * n + (b / n) * (a mod n) + (b mod n) * (a / n) + ((b mod n) * (a mod n)) / n)
+ by nia.
+ nia.
+Qed.
+Example Zmult_mod_idemp_l: forall a b n : Z, (a mod n * b) mod n = (a * b) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert (((a mod n) * b) / n = (b / n) * (a mod n) + ((b mod n) * (a mod n)) / n)
+ by nia.
+ assert ((a * b) / n = (b / n) * (a / n) * n + (b / n) * (a mod n) + (b mod n) * (a / n) + ((b mod n) * (a mod n)) / n)
+ by nia.
+ nia.
+Qed.
+Example Zminus_mod_idemp_r: forall a b n : Z, (a - b mod n) mod n = (a - b) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((a - b mod n) / n = a / n + ((a mod n) - (b mod n)) / n) by nia.
+ assert ((a - b) / n = a / n - b / n + ((a mod n) - (b mod n)) / n) by nia.
+ nia.
+Qed.
+Example Zminus_mod_idemp_l: forall a b n : Z, (a mod n - b) mod n = (a - b) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((a mod n - b) / n = - (b / n) + ((a mod n) - (b mod n)) / n) by nia.
+ assert ((a - b) / n = a / n - b / n + ((a mod n) - (b mod n)) / n) by nia.
+ nia.
+Qed.
+Example Z_mod_plus_full: forall a b c : Z, (a + b * c) mod c = a mod c.
+Proof.
+ intros a b c.
+ pose proof (Z_eq_dec_or ((a+b*c)/c) (a/c + b)).
+ nia.
+Qed.
+Example Zmult_mod_distr_l: forall a b c : Z, (c * a) mod (c * b) = c * (a mod b).
+Proof.
+ intros a b c.
+ destruct (Z_zerop c); try nia.
+ pose proof (Z_eq_dec_or ((c * a) / (c * b)) (a / b)).
+ nia.
+Qed.
+Example Z_mod_zero_opp_r: forall a b : Z, a mod b = 0 -> a mod - b = 0.
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or (a/b) (-(a/-b))).
+ nia.
+Qed.
+Example Zmod_1_l: forall a : Z, 1 < a -> 1 mod a = 1. Proof. t. Qed.
+Example Z_mod_1_l: forall a : Z, 1 < a -> 1 mod a = 1. Proof. t. Qed.
+Example Z_mod_mul: forall a b : Z, b <> 0 -> (a * b) mod b = 0.
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or ((a*b)/b) a).
+ nia.
+Qed.
+Example Zminus_mod: forall a b n : Z, (a - b) mod n = (a mod n - b mod n) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((a - b) / n = (a / n) - (b / n) + ((a mod n) - (b mod n)) / n) by nia.
+ nia.
+Qed.
+Example Zplus_mod: forall a b n : Z, (a + b) mod n = (a mod n + b mod n) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((a + b) / n = (a / n) + (b / n) + ((a mod n) + (b mod n)) / n) by nia.
+ nia.
+Qed.
+Example Zmult_mod: forall a b n : Z, (a * b) mod n = (a mod n * (b mod n)) mod n.
+Proof.
+ intros a b n.
+ destruct (Z_zerop n); [ subst; nia | ].
+ assert ((a * b) / n = n * (a / n) * (b / n) + (a mod n) * (b / n) + (a / n) * (b mod n) + ((a mod n) * (b mod n)) / n)
+ by nia.
+ nia.
+Qed.
+Example Z_mod_mod: forall a n : Z, n <> 0 -> (a mod n) mod n = a mod n. Proof. t. Qed.
+Example Z_mod_div: forall a b : Z, b <> 0 -> a mod b / b = 0. Proof. intros; nia. Qed.
+Example Z_div_exact_full_1: forall a b : Z, a = b * (a / b) -> a mod b = 0. Proof. intros; nia. Qed.
+Example Z_mod_pos_bound: forall a b : Z, 0 < b -> 0 <= a mod b < b. Proof. intros; nia. Qed.
+Example Z_mod_sign_mul: forall a b : Z, b <> 0 -> 0 <= a mod b * b. Proof. intros; nia. Qed.
+Example Z_mod_neg_bound: forall a b : Z, b < 0 -> b < a mod b <= 0. Proof. intros; nia. Qed.
+Example Z_mod_neg: forall a b : Z, b < 0 -> b < a mod b <= 0. Proof. intros; nia. Qed.
+Example div_mod_small: forall x y : Z, 0 <= x < y -> x mod y = x. Proof. t. Qed.
+Example Zmod_small: forall a n : Z, 0 <= a < n -> a mod n = a. Proof. t. Qed.
+Example Z_mod_small: forall a b : Z, 0 <= a < b -> a mod b = a. Proof. t. Qed.
+Example Z_div_zero_opp_full: forall a b : Z, a mod b = 0 -> - a / b = - (a / b). Proof. intros; nia. Qed.
+Example Z_mod_zero_opp: forall a b : Z, b > 0 -> a mod b = 0 -> - a mod b = 0.
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or (a/b) (-(-a/b))).
+ nia.
+Qed.
+Example Z_div_zero_opp_r: forall a b : Z, a mod b = 0 -> a / - b = - (a / b). Proof. intros; nia. Qed.
+Example Z_mod_lt: forall a b : Z, b > 0 -> 0 <= a mod b < b. Proof. intros; nia. Qed.
+Example Z_mod_opp_opp: forall a b : Z, b <> 0 -> - a mod - b = - (a mod b).
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or ((-a)/(-b)) ((a/b))).
+ nia.
+Qed.
+Example Z_mod_bound_pos: forall a b : Z, 0 <= a -> 0 < b -> 0 <= a mod b < b. Proof. intros; nia. Qed.
+Example Z_mod_opp_l_z: forall a b : Z, b <> 0 -> a mod b = 0 -> - a mod b = 0.
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or (a/b) (-(-a/b))).
+ nia.
+Qed.
+Example Z_mod_plus: forall a b c : Z, c > 0 -> (a + b * c) mod c = a mod c.
+Proof.
+ intros a b c.
+ pose proof (Z_eq_dec_or ((a+b*c)/c) (a/c+b)).
+ nia.
+Qed.
+Example Z_mod_opp_r_z: forall a b : Z, b <> 0 -> a mod b = 0 -> a mod - b = 0.
+Proof.
+ intros a b.
+ pose proof (Z_eq_dec_or (a/b) (-(a/-b))).
+ nia.
+Qed.
+Example Zmod_eq: forall a b : Z, b > 0 -> a mod b = a - a / b * b. Proof. intros; nia. Qed.
+Example Z_div_exact_2: forall a b : Z, b > 0 -> a mod b = 0 -> a = b * (a / b). Proof. intros; nia. Qed.
+Example Z_div_mod_eq: forall a b : Z, b > 0 -> a = b * (a / b) + a mod b. Proof. intros; nia. Qed.
+Example Z_div_exact_1: forall a b : Z, b > 0 -> a = b * (a / b) -> a mod b = 0. Proof. intros; nia. Qed.
+Example Z_mod_add: forall a b c : Z, c <> 0 -> (a + b * c) mod c = a mod c.
+Proof.
+ intros a b c.
+ pose proof (Z_eq_dec_or ((a+b*c)/c) (a/c+b)).
+ nia.
+Qed.
+Example Z_mod_nz_opp_r: forall a b : Z, a mod b <> 0 -> a mod - b = a mod b - b.
+Proof.
+ intros a b.
+ assert (a mod b <> 0 -> a / -b = -(a/b)-1) by t.
+ nia.
+Qed.
+Example Z_mul_mod_idemp_l: forall a b n : Z, n <> 0 -> (a mod n * b) mod n = (a * b) mod n.
+Proof.
+ intros a b n ?.
+ assert (((a mod n) * b) / n = (b / n) * (a mod n) + ((b mod n) * (a mod n)) / n)
+ by nia.
+ assert ((a * b) / n = (b / n) * (a / n) * n + (b / n) * (a mod n) + (b mod n) * (a / n) + ((b mod n) * (a mod n)) / n)
+ by nia.
+ nia.
+Qed.
+Example Z_mod_nz_opp_full: forall a b : Z, a mod b <> 0 -> - a mod b = b - a mod b.
+Proof.
+ intros a b.
+ assert (a mod b <> 0 -> -a/b = -1-a/b) by nia.
+ nia.
+Qed.
+Example Z_add_mod_idemp_r: forall a b n : Z, n <> 0 -> (a + b mod n) mod n = (a + b) mod n.
+Proof.
+ intros a b n ?.
+ assert ((a + b mod n) / n = (a / n) + (a mod n + b mod n) / n) by nia.
+ assert ((a + b) / n = (a / n) + (b / n) + (a mod n + b mod n) / n) by nia.
+ nia.
+Qed.
+Example Z_add_mod_idemp_l: forall a b n : Z, n <> 0 -> (a mod n + b) mod n = (a + b) mod n.
+Proof.
+ intros a b n ?.
+ assert ((a mod n + b) / n = (b / n) + (a mod n + b mod n) / n) by nia.
+ assert ((a + b) / n = (a / n) + (b / n) + (a mod n + b mod n) / n) by nia.
+ nia.
+Qed.
+Example Z_mul_mod_idemp_r: forall a b n : Z, n <> 0 -> (a * (b mod n)) mod n = (a * b) mod n.
+Proof.
+ intros a b n ?.
+ assert ((a * (b mod n)) / n = (a / n) * (b mod n) + ((a mod n) * (b mod n)) / n)
+ by nia.
+ assert ((a * b) / n = (b / n) * (a / n) * n + (b / n) * (a mod n) + (b mod n) * (a / n) + ((a mod n) * (b mod n)) / n)
+ by nia.
+ nia.
+Qed.
+Example Zmod_eq_full: forall a b : Z, b <> 0 -> a mod b = a - a / b * b. Proof. intros; nia. Qed.
+Example div_eq: forall x y : Z, y <> 0 -> x mod y = 0 -> x / y * y = x. Proof. intros; nia. Qed.
+Example Z_mod_eq: forall a b : Z, b <> 0 -> a mod b = a - b * (a / b). Proof. intros; nia. Qed.
+Example Z_mod_sign_nz: forall a b : Z, b <> 0 -> a mod b <> 0 -> Z.sgn (a mod b) = Z.sgn b. Proof. intros; nia. Qed.
+Example Z_div_exact_full_2: forall a b : Z, b <> 0 -> a mod b = 0 -> a = b * (a / b). Proof. intros; nia. Qed.
+Example Z_div_mod: forall a b : Z, b <> 0 -> a = b * (a / b) + a mod b. Proof. intros; nia. Qed.
+Example Z_add_mod: forall a b n : Z, n <> 0 -> (a + b) mod n = (a mod n + b mod n) mod n.
+Proof.
+ intros a b n ?.
+ assert ((a + b) / n = (a / n) + (b / n) + (a mod n + b mod n) / n) by nia.
+ nia.
+Qed.
+Example Z_mul_mod: forall a b n : Z, n <> 0 -> (a * b) mod n = (a mod n * (b mod n)) mod n.
+Proof.
+ intros a b n ?.
+ assert ((a * b) / n = (b / n) * (a / n) * n + (b / n) * (a mod n) + (b mod n) * (a / n) + ((a mod n) * (b mod n)) / n)
+ by nia.
+ nia.
+Qed.
+Example Z_div_exact: forall a b : Z, b <> 0 -> a = b * (a / b) <-> a mod b = 0. Proof. intros; nia. Qed.
+Example Z_div_opp_l_z: forall a b : Z, b <> 0 -> a mod b = 0 -> - a / b = - (a / b). Proof. intros; nia. Qed.
+Example Z_div_opp_r_z: forall a b : Z, b <> 0 -> a mod b = 0 -> a / - b = - (a / b). Proof. intros; nia. Qed.
+Example Z_mod_opp_r_nz: forall a b : Z, b <> 0 -> a mod b <> 0 -> a mod - b = a mod b - b.
+Proof.
+ intros a b.
+ assert (a mod b <> 0 -> a/(-b) = -1-a/b) by nia.
+ nia.
+Qed.
+Example Z_mul_mod_distr_r: forall a b c : Z, b <> 0 -> c <> 0 -> (a * c) mod (b * c) = a mod b * c.
+Proof.
+ intros a b c.
+ pose proof (Z_eq_dec_or ((a*c)/(b*c)) (a/b)).
+ nia.
+Qed.
+Example Z_mul_mod_distr_l: forall a b c : Z, b <> 0 -> c <> 0 -> (c * a) mod (c * b) = c * (a mod b).
+Proof.
+ intros a b c.
+ pose proof (Z_eq_dec_or ((c*a)/(c*b)) (a/b)).
+ nia.
+Qed.
+Example Z_mod_opp_l_nz: forall a b : Z, b <> 0 -> a mod b <> 0 -> - a mod b = b - a mod b.
+Proof.
+ intros a b.
+ assert (a mod b <> 0 -> -a/b = -1-a/b) by nia.
+ nia.
+Qed.
+Example mod_eq: forall x x' y : Z, x / y = x' / y -> x mod y = x' mod y -> y <> 0 -> x = x'. Proof. intros; nia. Qed.
+Example Z_div_nz_opp_r: forall a b : Z, a mod b <> 0 -> a / - b = - (a / b) - 1. Proof. intros; nia. Qed.
+Example Z_div_nz_opp_full: forall a b : Z, a mod b <> 0 -> - a / b = - (a / b) - 1. Proof. intros; nia. Qed.
+Example Zmod_unique: forall a b q r : Z, 0 <= r < b -> a = b * q + r -> r = a mod b.
+Proof.
+ intros a b q r ??.
+ assert (q = a / b) by nia.
+ nia.
+Qed.
+Example Z_mod_unique_neg: forall a b q r : Z, b < r <= 0 -> a = b * q + r -> r = a mod b.
+Proof.
+ intros a b q r ??.
+ assert (q = a / b) by nia.
+ nia.
+Qed.
+Example Z_mod_unique_pos: forall a b q r : Z, 0 <= r < b -> a = b * q + r -> r = a mod b.
+Proof.
+ intros a b q r ??.
+ assert (q = a / b) by nia.
+ nia.
+Qed.
+Example Z_rem_mul_r: forall a b c : Z, b <> 0 -> 0 < c -> a mod (b * c) = a mod b + b * ((a / b) mod c).
+Proof.
+ intros a b c ??.
+ assert (a / (b * c) = ((a / b) / c)) by nia.
+ nia.
+Qed.
+Example Z_mod_bound_or: forall a b : Z, b <> 0 -> 0 <= a mod b < b \/ b < a mod b <= 0. Proof. intros; nia. Qed.
+Example Z_div_opp_l_nz: forall a b : Z, b <> 0 -> a mod b <> 0 -> - a / b = - (a / b) - 1. Proof. intros; nia. Qed.
+Example Z_div_opp_r_nz: forall a b : Z, b <> 0 -> a mod b <> 0 -> a / - b = - (a / b) - 1. Proof. intros; nia. Qed.
+Example Z_mod_small_iff: forall a b : Z, b <> 0 -> a mod b = a <-> 0 <= a < b \/ b < a <= 0. Proof. t. Qed.
+Example Z_mod_unique: forall a b q r : Z, 0 <= r < b \/ b < r <= 0 -> a = b * q + r -> r = a mod b.
+Proof.
+ intros a b q r ??.
+ assert (q = a/b) by nia.
+ nia.
+Qed.
+Example Z_opp_mod_bound_or: forall a b : Z, b <> 0 -> 0 <= - (a mod b) < - b \/ - b < - (a mod b) <= 0. Proof. intros; nia. Qed.
+
+Example Zdiv_0_r: forall a : Z, a / 0 = 0. Proof. intros; nia. Qed.
+Example Zdiv_0_l: forall a : Z, 0 / a = 0. Proof. intros; nia. Qed.
+Example Z_div_1_r: forall a : Z, a / 1 = a. Proof. intros; nia. Qed.
+Example Zdiv_1_r: forall a : Z, a / 1 = a. Proof. intros; nia. Qed.
+Example Zdiv_opp_opp: forall a b : Z, - a / - b = a / b. Proof. intros; nia. Qed.
+Example Z_div_0_l: forall a : Z, a <> 0 -> 0 / a = 0. Proof. intros; nia. Qed.
+Example Z_div_pos: forall a b : Z, b > 0 -> 0 <= a -> 0 <= a / b. Proof. intros; nia. Qed.
+Example Z_div_ge0: forall a b : Z, b > 0 -> a >= 0 -> a / b >= 0. Proof. intros; nia. Qed.
+Example Z_div_pos': forall a b : Z, 0 <= a -> 0 < b -> 0 <= a / b. Proof. intros; nia. Qed.
+Example Z_mult_div_ge: forall a b : Z, b > 0 -> b * (a / b) <= a. Proof. intros; nia. Qed.
+Example Z_mult_div_ge_neg: forall a b : Z, b < 0 -> b * (a / b) >= a. Proof. intros; nia. Qed.
+Example Z_mul_div_le: forall a b : Z, 0 < b -> b * (a / b) <= a. Proof. intros; nia. Qed.
+Example Z_mul_div_ge: forall a b : Z, b < 0 -> a <= b * (a / b). Proof. intros; nia. Qed.
+Example Z_div_same: forall a : Z, a > 0 -> a / a = 1. Proof. intros; nia. Qed.
+Example Z_div_mult: forall a b : Z, b > 0 -> a * b / b = a. Proof. intros; nia. Qed.
+Example Z_mul_succ_div_gt: forall a b : Z, 0 < b -> a < b * Z.succ (a / b). Proof. intros; nia. Qed.
+Example Z_mul_succ_div_lt: forall a b : Z, b < 0 -> b * Z.succ (a / b) < a. Proof. intros; nia. Qed.
+Example Zdiv_1_l: forall a : Z, 1 < a -> 1 / a = 0. Proof. intros; nia. Qed.
+Example Z_div_1_l: forall a : Z, 1 < a -> 1 / a = 0. Proof. intros; nia. Qed.
+Example Z_div_str_pos: forall a b : Z, 0 < b <= a -> 0 < a / b. Proof. intros; nia. Qed.
+Example Z_div_ge: forall a b c : Z, c > 0 -> a >= b -> a / c >= b / c. Proof. intros; nia. Qed.
+Example Z_div_mult_full: forall a b : Z, b <> 0 -> a * b / b = a. Proof. intros; nia. Qed.
+Example Z_div_same': forall a : Z, a <> 0 -> a / a = 1. Proof. intros; nia. Qed.
+Example Zdiv_lt_upper_bound: forall a b q : Z, 0 < b -> a < q * b -> a / b < q. Proof. intros; nia. Qed.
+Example Z_div_mul: forall a b : Z, b <> 0 -> a * b / b = a. Proof. intros; nia. Qed.
+Example Z_div_lt: forall a b : Z, 0 < a -> 1 < b -> a / b < a. Proof. intros; nia. Qed.
+Example Z_div_le_mono: forall a b c : Z, 0 < c -> a <= b -> a / c <= b / c. Proof. intros; nia. Qed.
+Example Zdiv_sgn: forall a b : Z, 0 <= Z.sgn (a / b) * Z.sgn a * Z.sgn b. Proof. intros; nia. Qed.
+Example Z_div_same_full: forall a : Z, a <> 0 -> a / a = 1. Proof. intros; nia. Qed.
+Example Z_div_lt_upper_bound: forall a b q : Z, 0 < b -> a < b * q -> a / b < q. Proof. intros; nia. Qed.
+Example Z_div_le: forall a b c : Z, c > 0 -> a <= b -> a / c <= b / c. Proof. intros; nia. Qed.
+Example Z_div_le_lower_bound: forall a b q : Z, 0 < b -> b * q <= a -> q <= a / b. Proof. intros; nia. Qed.
+Example Zdiv_le_lower_bound: forall a b q : Z, 0 < b -> q * b <= a -> q <= a / b. Proof. intros; nia. Qed.
+Example Zdiv_le_upper_bound: forall a b q : Z, 0 < b -> a <= q * b -> a / b <= q. Proof. intros; nia. Qed.
+Example Z_div_le_upper_bound: forall a b q : Z, 0 < b -> a <= b * q -> a / b <= q. Proof. intros; nia. Qed.
+Example Z_div_small: forall a b : Z, 0 <= a < b -> a / b = 0. Proof. intros; nia. Qed.
+Example Zdiv_small: forall a b : Z, 0 <= a < b -> a / b = 0. Proof. intros; nia. Qed.
+Example Z_div_opp_opp: forall a b : Z, b <> 0 -> - a / - b = a / b. Proof. intros; nia. Qed.
+Example Zdiv_mult_cancel_r: forall a b c : Z, c <> 0 -> a * c / (b * c) = a / b. Proof. intros; nia. Qed.
+Example Z_div_unique_exact: forall a b q : Z, b <> 0 -> a = b * q -> q = a / b. Proof. intros; nia. Qed.
+Example Zdiv_mult_cancel_l: forall a b c : Z, c <> 0 -> c * a / (c * b) = a / b. Proof. intros; nia. Qed.
+Example Zdiv_le_compat_l: forall p q r : Z, 0 <= p -> 0 < q < r -> p / r <= p / q.
+Proof.
+ intros p q r ??.
+ assert (p mod r <= p mod q \/ p mod q <= p mod r) by nia.
+ assert (0 <= p / r) by nia.
+ assert (0 <= p / q) by nia.
+ nia.
+Qed.
+Example Z_div_le_compat_l: forall p q r : Z, 0 <= p -> 0 < q <= r -> p / r <= p / q.
+Proof.
+ intros p q r ??.
+ assert (p mod r <= p mod q \/ p mod q <= p mod r) by nia.
+ assert (0 <= p / r) by nia.
+ assert (0 <= p / q) by nia.
+ nia.
+Qed.
+Example Zdiv_Zdiv: forall a b c : Z, 0 <= b -> 0 <= c -> a / b / c = a / (b * c). Proof. intros; nia. Qed.
+Example Z_div_plus: forall a b c : Z, c > 0 -> (a + b * c) / c = a / c + b. Proof. intros; nia. Qed.
+Example Z_div_lt': forall a b : Z, b >= 2 -> a > 0 -> a / b < a. Proof. intros; nia. Qed.
+Example Zdiv_mult_le: forall a b c : Z, 0 <= a -> 0 <= b -> 0 <= c -> c * (a / b) <= c * a / b. Proof. intros; nia. Qed.
+Example Z_div_add_l: forall a b c : Z, b <> 0 -> (a * b + c) / b = a + c / b. Proof. intros; nia. Qed.
+Example Z_div_plus_full_l: forall a b c : Z, b <> 0 -> (a * b + c) / b = a + c / b. Proof. intros; nia. Qed.
+Example Z_div_add: forall a b c : Z, c <> 0 -> (a + b * c) / c = a / c + b. Proof. intros; nia. Qed.
+Example Z_div_plus_full: forall a b c : Z, c <> 0 -> (a + b * c) / c = a / c + b. Proof. intros; nia. Qed.
+Example Z_div_mul_le: forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a / b) <= c * a / b. Proof. intros; nia. Qed.
+Example Z_div_mul_cancel_r: forall a b c : Z, b <> 0 -> c <> 0 -> a * c / (b * c) = a / b. Proof. intros; nia. Qed.
+Example Z_div_div: forall a b c : Z, b <> 0 -> 0 < c -> a / b / c = a / (b * c). Proof. intros; nia. Qed.
+Example Z_div_mul_cancel_l: forall a b c : Z, b <> 0 -> c <> 0 -> c * a / (c * b) = a / b. Proof. intros; nia. Qed.
+Example Z_div_unique_neg: forall a b q r : Z, b < r <= 0 -> a = b * q + r -> q = a / b. Proof. intros; nia. Qed.
+Example Zdiv_unique: forall a b q r : Z, 0 <= r < b -> a = b * q + r -> q = a / b. Proof. intros; nia. Qed.
+Example Z_div_unique_pos: forall a b q r : Z, 0 <= r < b -> a = b * q + r -> q = a / b. Proof. intros; nia. Qed.
+Example Z_div_small_iff: forall a b : Z, b <> 0 -> a / b = 0 <-> 0 <= a < b \/ b < a <= 0. Proof. intros; nia. Qed.
+Example Z_div_unique: forall a b q r : Z, 0 <= r < b \/ b < r <= 0 -> a = b * q + r -> q = a / b. Proof. intros; nia. Qed.
+
+(** Now we do the same, but with [Z.quot] and [Z.rem] instead. *)
+Lemma N2Z_inj_quot : forall n m : N, Z.of_N (n / m) = Z.of_N n ÷ Z.of_N m. Proof. intros; nia. Qed.
+Lemma N2Z_inj_rem : forall n m : N, Z.of_N (n mod m) = Z.rem (Z.of_N n) (Z.of_N m). Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_mul_quot_ge : forall a b : Z, a <= 0 -> b <> 0 -> a <= b * (a ÷ b) <= 0.
+Proof. intros; destruct (Z_zerop (a ÷ b)); nia. Qed.
+Lemma OrdersEx_Z_as_DT_mul_quot_le : forall a b : Z, 0 <= a -> b <> 0 -> 0 <= b * (a ÷ b) <= a. Proof. intros; destruct (Z_zerop (a ÷ b)); nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_0_l : forall a : Z, 0 < a -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_1_r : forall a : Z, 0 <= a -> a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_add : forall a b c : Z, 0 <= a -> 0 <= a + b * c -> 0 < c -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_add_l : forall a b c : Z, 0 <= c -> 0 <= a * b + c -> 0 < b -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_div : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a ÷ b ÷ c = a ÷ (b * c).
+Proof. intros; assert (0 < b * c) by nia; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q.
+Proof.
+ intros.
+ destruct (Z_zerop p), (Z_zerop (p ÷ r)), (Z_zerop (p ÷ q)); subst; [ nia.. | ].
+ assert (0 < q) by nia; assert (0 < r) by nia; assert (0 < p) by nia.
+ nia.
+Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_le_lower_bound : forall a b q : Z, 0 <= a -> 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_le_mono : forall a b c : Z, 0 < c -> 0 <= a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_le_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_mul_cancel_l : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_mul_cancel_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_mul : forall a b : Z, 0 <= a -> 0 < b -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_same : forall a : Z, 0 < a -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_small_iff : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = 0 <-> a < b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_str_pos_iff : forall a b : Z, 0 <= a -> 0 < b -> 0 < a ÷ b <-> b <= a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_unique_exact : forall a b q : Z, 0 <= a -> 0 < b -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_div_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_Private_Div_NZQuot_mul_div_le : forall a b : Z, 0 <= a -> 0 < b -> b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_0_l : forall a : Z, a <> 0 -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_1_r : forall a : Z, a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_add : forall a b c : Z, c <> 0 -> 0 <= (a + b * c) * a -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_add_l : forall a b c : Z, b <> 0 -> 0 <= (a * b + c) * c -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_div_nonneg : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = a / b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q.
+Proof.
+ intros.
+ destruct (Z_zerop p), (Z_zerop (p ÷ r)), (Z_zerop (p ÷ q)); [ subst; nia.. | ].
+ assert (0 < p) by nia; assert (0 < r) by nia.
+ nia.
+Qed.
+Lemma OrdersEx_Z_as_DT_quot_le_lower_bound : forall a b q : Z, 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_le_mono : forall a b c : Z, 0 < c -> a <= b -> a ÷ c <= b ÷ c.
+Proof.
+ intros.
+ destruct (Z_zerop a), (Z_zerop b), (Z_zerop (a ÷ c)), (Z_zerop (b ÷ c)); [ subst; nia.. | ].
+ nia.
+Qed.
+Lemma OrdersEx_Z_as_DT_quot_le_upper_bound : forall a b q : Z, 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_mul_cancel_l : forall a b c : Z, b <> 0 -> c <> 0 -> c * a ÷ (c * b) = a ÷ b.
+Proof.
+ intros.
+ assert (c * b <> 0) by nia.
+ destruct (Z_zerop a), (Z_zerop (c * a)); subst; [ nia | exfalso; nia.. | ].
+Abort.
+Lemma OrdersEx_Z_as_DT_quot_mul_cancel_r : forall a b c : Z, b <> 0 -> c <> 0 -> a * c ÷ (b * c) = a ÷ b. Proof. Abort.
+Lemma OrdersEx_Z_as_DT_quot_mul : forall a b : Z, b <> 0 -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_opp_l : forall a b : Z, b <> 0 -> - a ÷ b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_opp_opp : forall a b : Z, b <> 0 -> - a ÷ - b = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_opp_r : forall a b : Z, b <> 0 -> a ÷ - b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_quot : forall a b c : Z, b <> 0 -> c <> 0 -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros; assert (b * c <> 0) by nia. Abort.
+Lemma OrdersEx_Z_as_DT_quot_same : forall a : Z, a <> 0 -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_unique_exact : forall a b q : Z, b <> 0 -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_DT_quot_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_mul_quot_ge : forall a b : Z, a <= 0 -> b <> 0 -> a <= b * (a ÷ b) <= 0. Proof. intros. Fail nia. Abort.
+Lemma OrdersEx_Z_as_OT_mul_quot_le : forall a b : Z, 0 <= a -> b <> 0 -> 0 <= b * (a ÷ b) <= a. Proof. intros. Fail nia. Abort.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_0_l : forall a : Z, 0 < a -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_1_r : forall a : Z, 0 <= a -> a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_add : forall a b c : Z, 0 <= a -> 0 <= a + b * c -> 0 < c -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_add_l : forall a b c : Z, 0 <= c -> 0 <= a * b + c -> 0 < b -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_div : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q. Proof. intros. Abort.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_le_lower_bound : forall a b q : Z, 0 <= a -> 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_le_mono : forall a b c : Z, 0 < c -> 0 <= a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_le_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_mul_cancel_l : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_mul_cancel_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_mul : forall a b : Z, 0 <= a -> 0 < b -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_same : forall a : Z, 0 < a -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_small_iff : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = 0 <-> a < b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_str_pos_iff : forall a b : Z, 0 <= a -> 0 < b -> 0 < a ÷ b <-> b <= a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_unique_exact : forall a b q : Z, 0 <= a -> 0 < b -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_div_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_Private_Div_NZQuot_mul_div_le : forall a b : Z, 0 <= a -> 0 < b -> b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_0_l : forall a : Z, a <> 0 -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_1_r : forall a : Z, a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_add : forall a b c : Z, c <> 0 -> 0 <= (a + b * c) * a -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_add_l : forall a b c : Z, b <> 0 -> 0 <= (a * b + c) * c -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_div_nonneg : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = a / b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q. Proof. intros. Fail nia. Abort.
+Lemma OrdersEx_Z_as_OT_quot_le_lower_bound : forall a b q : Z, 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_le_mono : forall a b c : Z, 0 < c -> a <= b -> a ÷ c <= b ÷ c. Proof. intros. Fail nia. Abort.
+Lemma OrdersEx_Z_as_OT_quot_le_upper_bound : forall a b q : Z, 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_mul_cancel_l : forall a b c : Z, b <> 0 -> c <> 0 -> c * a ÷ (c * b) = a ÷ b. Proof. intros. Abort.
+Lemma OrdersEx_Z_as_OT_quot_mul_cancel_r : forall a b c : Z, b <> 0 -> c <> 0 -> a * c ÷ (b * c) = a ÷ b. Proof. intros. Abort.
+Lemma OrdersEx_Z_as_OT_quot_mul : forall a b : Z, b <> 0 -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_opp_l : forall a b : Z, b <> 0 -> - a ÷ b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_opp_opp : forall a b : Z, b <> 0 -> - a ÷ - b = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_opp_r : forall a b : Z, b <> 0 -> a ÷ - b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_quot : forall a b c : Z, b <> 0 -> c <> 0 -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros. Abort.
+Lemma OrdersEx_Z_as_OT_quot_same : forall a : Z, a <> 0 -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_unique_exact : forall a b q : Z, b <> 0 -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma OrdersEx_Z_as_OT_quot_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z2N_inj_quot : forall n m : Z, 0 <= n -> 0 <= m -> Z.to_N (n ÷ m) = (Z.to_N n / Z.to_N m)%N.
+Proof. intros; destruct (Z_zerop n), (Z_zerop m), (Z_zerop (n ÷ m)); [ subst; try nia.. | ]. Abort.
+Lemma Z2N_inj_rem : forall n m : Z, 0 <= n -> 0 <= m -> Z.to_N (Z.rem n m) = (Z.to_N n mod Z.to_N m)%N. Proof. intros. Abort.
+Lemma Zabs2N_inj_quot : forall n m : Z, Z.abs_N (n ÷ m) = (Z.abs_N n / Z.abs_N m)%N. Proof. intros. Abort.
+Lemma Zabs2N_inj_rem : forall n m : Z, Z.abs_N (Z.rem n m) = (Z.abs_N n mod Z.abs_N m)%N. Proof. intros. Abort.
+(* Some of these don't work, and I haven't gone through and figured out which ones yet, so they're all commented out for now *)
+(*
+Lemma Z_add_rem : forall a b n : Z, n <> 0 -> 0 <= a * b -> Z.rem (a + b) n = Z.rem (Z.rem a n + Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma Z_add_rem_idemp_l : forall a b n : Z, n <> 0 -> 0 <= a * b -> Z.rem (Z.rem a n + b) n = Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma Z_add_rem_idemp_r : forall a b n : Z, n <> 0 -> 0 <= a * b -> Z.rem (a + Z.rem b n) n = Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_add_rem : forall a b n : Z, n <> 0 -> 0 <= a * b -> ZBinary.Z.rem (a + b) n = ZBinary.Z.rem (ZBinary.Z.rem a n + ZBinary.Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_add_rem_idemp_l : forall a b n : Z, n <> 0 -> 0 <= a * b -> ZBinary.Z.rem (ZBinary.Z.rem a n + b) n = ZBinary.Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_add_rem_idemp_r : forall a b n : Z, n <> 0 -> 0 <= a * b -> ZBinary.Z.rem (a + ZBinary.Z.rem b n) n = ZBinary.Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_gcd_quot_gcd : forall a b g : Z, g <> 0 -> g = ZBinary.Z.gcd a b -> ZBinary.Z.gcd (a ÷ g) (b ÷ g) = 1. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_gcd_rem : forall a b : Z, b <> 0 -> ZBinary.Z.gcd (ZBinary.Z.rem a b) b = ZBinary.Z.gcd b a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mod_mul_r : forall a b c : Z, b <> 0 -> c <> 0 -> ZBinary.Z.rem a (b * c) = ZBinary.Z.rem a b + b * ZBinary.Z.rem (a ÷ b) c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_pred_quot_gt : forall a b : Z, 0 <= a -> b < 0 -> a < b * ZBinary.Z.pred (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_pred_quot_lt : forall a b : Z, a <= 0 -> 0 < b -> b * ZBinary.Z.pred (a ÷ b) < a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_quot_ge : forall a b : Z, a <= 0 -> b <> 0 -> a <= b * (a ÷ b) <= 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_quot_le : forall a b : Z, 0 <= a -> b <> 0 -> 0 <= b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_rem_distr_l : forall a b c : Z, b <> 0 -> c <> 0 -> ZBinary.Z.rem (c * a) (c * b) = c * ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_rem_distr_r : forall a b c : Z, b <> 0 -> c <> 0 -> ZBinary.Z.rem (a * c) (b * c) = ZBinary.Z.rem a b * c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_rem : forall a b n : Z, n <> 0 -> ZBinary.Z.rem (a * b) n = ZBinary.Z.rem (ZBinary.Z.rem a n * ZBinary.Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_rem_idemp_l : forall a b n : Z, n <> 0 -> ZBinary.Z.rem (ZBinary.Z.rem a n * b) n = ZBinary.Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_rem_idemp_r : forall a b n : Z, n <> 0 -> ZBinary.Z.rem (a * ZBinary.Z.rem b n) n = ZBinary.Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_succ_quot_gt : forall a b : Z, 0 <= a -> 0 < b -> a < b * ZBinary.Z.succ (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_mul_succ_quot_lt : forall a b : Z, a <= 0 -> b < 0 -> b * ZBinary.Z.succ (a ÷ b) < a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_add_mod : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> ZBinary.Z.rem (a + b) n = ZBinary.Z.rem (ZBinary.Z.rem a n + ZBinary.Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_add_mod_idemp_l : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> ZBinary.Z.rem (ZBinary.Z.rem a n + b) n = ZBinary.Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_add_mod_idemp_r : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> ZBinary.Z.rem (a + ZBinary.Z.rem b n) n = ZBinary.Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_0_l : forall a : Z, 0 < a -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_1_r : forall a : Z, 0 <= a -> a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_add : forall a b c : Z, 0 <= a -> 0 <= a + b * c -> 0 < c -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_add_l : forall a b c : Z, 0 <= c -> 0 <= a * b + c -> 0 < b -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_div : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_exact : forall a b : Z, 0 <= a -> 0 < b -> a = b * (a ÷ b) <-> ZBinary.Z.rem a b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_le_lower_bound : forall a b q : Z, 0 <= a -> 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_le_mono : forall a b c : Z, 0 < c -> 0 <= a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_le_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_mul_cancel_l : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_mul_cancel_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_mul : forall a b : Z, 0 <= a -> 0 < b -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_same : forall a : Z, 0 < a -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_small_iff : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = 0 <-> a < b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_str_pos_iff : forall a b : Z, 0 <= a -> 0 < b -> 0 < a ÷ b <-> b <= a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_unique_exact : forall a b q : Z, 0 <= a -> 0 < b -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_div_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_0_l : forall a : Z, 0 < a -> ZBinary.Z.rem 0 a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_1_l : forall a : Z, 1 < a -> ZBinary.Z.rem 1 a = 1. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_1_r : forall a : Z, 0 <= a -> ZBinary.Z.rem a 1 = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_add : forall a b c : Z, 0 <= a -> 0 <= a + b * c -> 0 < c -> ZBinary.Z.rem (a + b * c) c = ZBinary.Z.rem a c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_divides : forall a b : Z, 0 <= a -> 0 < b -> ZBinary.Z.rem a b = 0 <-> (exists c : Z, a = b * c). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_le : forall a b : Z, 0 <= a -> 0 < b -> ZBinary.Z.rem a b <= a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_mod : forall a n : Z, 0 <= a -> 0 < n -> ZBinary.Z.rem (ZBinary.Z.rem a n) n = ZBinary.Z.rem a n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_mul : forall a b : Z, 0 <= a -> 0 < b -> ZBinary.Z.rem (a * b) b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_mul_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> ZBinary.Z.rem a (b * c) = ZBinary.Z.rem a b + b * ZBinary.Z.rem (a ÷ b) c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_same : forall a : Z, 0 < a -> ZBinary.Z.rem a a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_small : forall a b : Z, 0 <= a < b -> ZBinary.Z.rem a b = a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_small_iff : forall a b : Z, 0 <= a -> 0 < b -> ZBinary.Z.rem a b = a <-> a < b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mod_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> r = ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_div_le : forall a b : Z, 0 <= a -> 0 < b -> b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_mod_distr_l : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> ZBinary.Z.rem (c * a) (c * b) = c * ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_mod_distr_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> ZBinary.Z.rem (a * c) (b * c) = ZBinary.Z.rem a b * c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_mod : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> ZBinary.Z.rem (a * b) n = ZBinary.Z.rem (ZBinary.Z.rem a n * ZBinary.Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_mod_idemp_l : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> ZBinary.Z.rem (ZBinary.Z.rem a n * b) n = ZBinary.Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_mod_idemp_r : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> ZBinary.Z.rem (a * ZBinary.Z.rem b n) n = ZBinary.Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_NZQuot_mul_succ_div_gt : forall a b : Z, 0 <= a -> 0 < b -> a < b * ZBinary.Z.succ (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_Private_Div_Quot2Div_div_mod : forall a b : Z, b <> 0 -> a = b * (a ÷ b) + ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+ZBinary_Z_Private_Div_Quot2Div_div_wd Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) ZBinary.Z.quot
+Lemma ZBinary_Z_Private_Div_Quot2Div_mod_bound_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= ZBinary.Z.rem a b < b. Proof. intros; nia. Qed.
+ZBinary_Z_Private_Div_Quot2Div_mod_wd Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) ZBinary.Z.rem
+Lemma ZBinary_Z_quot_0_l : forall a : Z, a <> 0 -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_1_r : forall a : Z, a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_abs : forall a b : Z, b <> 0 -> ZBinary.Z.abs a ÷ ZBinary.Z.abs b = ZBinary.Z.abs (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_abs_l : forall a b : Z, b <> 0 -> ZBinary.Z.abs a ÷ b = ZBinary.Z.sgn a * (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_abs_r : forall a b : Z, b <> 0 -> a ÷ ZBinary.Z.abs b = ZBinary.Z.sgn b * (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_add : forall a b c : Z, c <> 0 -> 0 <= (a + b * c) * a -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_add_l : forall a b c : Z, b <> 0 -> 0 <= (a * b + c) * c -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_div : forall a b : Z, b <> 0 -> a ÷ b = ZBinary.Z.sgn a * ZBinary.Z.sgn b * (ZBinary.Z.abs a / ZBinary.Z.abs b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_div_nonneg : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = a / b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_exact : forall a b : Z, b <> 0 -> a = b * (a ÷ b) <-> ZBinary.Z.rem a b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_le_lower_bound : forall a b q : Z, 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_le_mono : forall a b c : Z, 0 < c -> a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_le_upper_bound : forall a b q : Z, 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_mul_cancel_l : forall a b c : Z, b <> 0 -> c <> 0 -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_mul_cancel_r : forall a b c : Z, b <> 0 -> c <> 0 -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_mul : forall a b : Z, b <> 0 -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_opp_l : forall a b : Z, b <> 0 -> - a ÷ b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_opp_opp : forall a b : Z, b <> 0 -> - a ÷ - b = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_opp_r : forall a b : Z, b <> 0 -> a ÷ - b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_quot : forall a b c : Z, b <> 0 -> c <> 0 -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_rem' : forall a b : Z, a = b * (a ÷ b) + ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_rem : forall a b : Z, b <> 0 -> a = b * (a ÷ b) + ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_same : forall a : Z, a <> 0 -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_small_iff : forall a b : Z, b <> 0 -> a ÷ b = 0 <-> ZBinary.Z.abs a < ZBinary.Z.abs b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_unique_exact : forall a b q : Z, b <> 0 -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_quot_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+ZBinary_Z_quot_wd Morphisms.Proper (Morphisms.respectful ZBinary.Z.eq (Morphisms.respectful ZBinary.Z.eq ZBinary.Z.eq)) ZBinary.Z.quot
+Lemma ZBinary_Z_rem_0_l : forall a : Z, a <> 0 -> ZBinary.Z.rem 0 a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_1_l : forall a : Z, 1 < a -> ZBinary.Z.rem 1 a = 1. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_1_r : forall a : Z, ZBinary.Z.rem a 1 = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_abs : forall a b : Z, b <> 0 -> ZBinary.Z.rem (ZBinary.Z.abs a) (ZBinary.Z.abs b) = ZBinary.Z.abs (ZBinary.Z.rem a b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_abs_l : forall a b : Z, b <> 0 -> ZBinary.Z.rem (ZBinary.Z.abs a) b = ZBinary.Z.abs (ZBinary.Z.rem a b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_abs_r : forall a b : Z, b <> 0 -> ZBinary.Z.rem a (ZBinary.Z.abs b) = ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_add : forall a b c : Z, c <> 0 -> 0 <= (a + b * c) * a -> ZBinary.Z.rem (a + b * c) c = ZBinary.Z.rem a c. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_bound_abs : forall a b : Z, b <> 0 -> ZBinary.Z.abs (ZBinary.Z.rem a b) < ZBinary.Z.abs b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_bound_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= ZBinary.Z.rem a b < b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_eq : forall a b : Z, b <> 0 -> ZBinary.Z.rem a b = a - b * (a ÷ b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_le : forall a b : Z, 0 <= a -> 0 < b -> ZBinary.Z.rem a b <= a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_mod_eq_0 : forall a b : Z, b <> 0 -> ZBinary.Z.rem a b = 0 <-> a mod b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_mod : forall a b : Z, b <> 0 -> ZBinary.Z.rem a b = ZBinary.Z.sgn a * (ZBinary.Z.abs a mod ZBinary.Z.abs b). Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_mod_nonneg : forall a b : Z, 0 <= a -> 0 < b -> ZBinary.Z.rem a b = a mod b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_mul : forall a b : Z, b <> 0 -> ZBinary.Z.rem (a * b) b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_nonneg : forall a b : Z, b <> 0 -> 0 <= a -> 0 <= ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_nonpos : forall a b : Z, b <> 0 -> a <= 0 -> ZBinary.Z.rem a b <= 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_opp_l : forall a b : Z, b <> 0 -> ZBinary.Z.rem (- a) b = - ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_opp_l' : forall a b : Z, ZBinary.Z.rem (- a) b = - ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_opp_opp : forall a b : Z, b <> 0 -> ZBinary.Z.rem (- a) (- b) = - ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_opp_r : forall a b : Z, b <> 0 -> ZBinary.Z.rem a (- b) = ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_opp_r' : forall a b : Z, ZBinary.Z.rem a (- b) = ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_quot : forall a b : Z, b <> 0 -> ZBinary.Z.rem a b ÷ b = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_rem : forall a n : Z, n <> 0 -> ZBinary.Z.rem (ZBinary.Z.rem a n) n = ZBinary.Z.rem a n. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_same : forall a : Z, a <> 0 -> ZBinary.Z.rem a a = 0. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_sign : forall a b : Z, a <> 0 -> b <> 0 -> ZBinary.Z.sgn (ZBinary.Z.rem a b) <> - ZBinary.Z.sgn a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_sign_mul : forall a b : Z, b <> 0 -> 0 <= ZBinary.Z.rem a b * a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_sign_nz : forall a b : Z, b <> 0 -> ZBinary.Z.rem a b <> 0 -> ZBinary.Z.sgn (ZBinary.Z.rem a b) = ZBinary.Z.sgn a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_small : forall a b : Z, 0 <= a < b -> ZBinary.Z.rem a b = a. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_small_iff : forall a b : Z, b <> 0 -> ZBinary.Z.rem a b = a <-> ZBinary.Z.abs a < ZBinary.Z.abs b. Proof. intros; nia. Qed.
+Lemma ZBinary_Z_rem_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> r = ZBinary.Z.rem a b. Proof. intros; nia. Qed.
+ZBinary_Z_rem_wd Morphisms.Proper (Morphisms.respectful ZBinary.Z.eq (Morphisms.respectful ZBinary.Z.eq ZBinary.Z.eq)) ZBinary.Z.rem
+Lemma Z_gcd_quot_gcd : forall a b g : Z, g <> 0 -> g = Z.gcd a b -> Z.gcd (a ÷ g) (b ÷ g) = 1. Proof. intros; nia. Qed.
+Lemma Z_gcd_rem : forall a b : Z, b <> 0 -> Z.gcd (Z.rem a b) b = Z.gcd b a. Proof. intros; nia. Qed.
+Lemma Z_mod_mul_r : forall a b c : Z, b <> 0 -> c <> 0 -> Z.rem a (b * c) = Z.rem a b + b * Z.rem (a ÷ b) c. Proof. intros; nia. Qed.
+Lemma Z_mul_pred_quot_gt : forall a b : Z, 0 <= a -> b < 0 -> a < b * Z.pred (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_mul_pred_quot_lt : forall a b : Z, a <= 0 -> 0 < b -> b * Z.pred (a ÷ b) < a. Proof. intros; nia. Qed.
+Lemma Z_mul_quot_ge : forall a b : Z, a <= 0 -> b <> 0 -> a <= b * (a ÷ b) <= 0. Proof. intros; nia. Qed.
+Lemma Z_mul_quot_le : forall a b : Z, 0 <= a -> b <> 0 -> 0 <= b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma Z_mul_rem_distr_l : forall a b c : Z, b <> 0 -> c <> 0 -> Z.rem (c * a) (c * b) = c * Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_mul_rem_distr_r : forall a b c : Z, b <> 0 -> c <> 0 -> Z.rem (a * c) (b * c) = Z.rem a b * c. Proof. intros; nia. Qed.
+Lemma Z_mul_rem : forall a b n : Z, n <> 0 -> Z.rem (a * b) n = Z.rem (Z.rem a n * Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma Z_mul_rem_idemp_l : forall a b n : Z, n <> 0 -> Z.rem (Z.rem a n * b) n = Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma Z_mul_rem_idemp_r : forall a b n : Z, n <> 0 -> Z.rem (a * Z.rem b n) n = Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma Z_mul_succ_quot_gt : forall a b : Z, 0 <= a -> 0 < b -> a < b * Z.succ (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_mul_succ_quot_lt : forall a b : Z, a <= 0 -> b < 0 -> b * Z.succ (a ÷ b) < a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_add_mod : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> Z.rem (a + b) n = Z.rem (Z.rem a n + Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_add_mod_idemp_l : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> Z.rem (Z.rem a n + b) n = Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_add_mod_idemp_r : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> Z.rem (a + Z.rem b n) n = Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_0_l : forall a : Z, 0 < a -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_1_r : forall a : Z, 0 <= a -> a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_add : forall a b c : Z, 0 <= a -> 0 <= a + b * c -> 0 < c -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_add_l : forall a b c : Z, 0 <= c -> 0 <= a * b + c -> 0 < b -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_div : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_exact : forall a b : Z, 0 <= a -> 0 < b -> a = b * (a ÷ b) <-> Z.rem a b = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_le_lower_bound : forall a b q : Z, 0 <= a -> 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_le_mono : forall a b c : Z, 0 < c -> 0 <= a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_le_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_mul_cancel_l : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_mul_cancel_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_mul : forall a b : Z, 0 <= a -> 0 < b -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_same : forall a : Z, 0 < a -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_small_iff : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = 0 <-> a < b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_str_pos_iff : forall a b : Z, 0 <= a -> 0 < b -> 0 < a ÷ b <-> b <= a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_unique_exact : forall a b q : Z, 0 <= a -> 0 < b -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_div_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_0_l : forall a : Z, 0 < a -> Z.rem 0 a = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_1_l : forall a : Z, 1 < a -> Z.rem 1 a = 1. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_1_r : forall a : Z, 0 <= a -> Z.rem a 1 = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_add : forall a b c : Z, 0 <= a -> 0 <= a + b * c -> 0 < c -> Z.rem (a + b * c) c = Z.rem a c. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_divides : forall a b : Z, 0 <= a -> 0 < b -> Z.rem a b = 0 <-> (exists c : Z, a = b * c). Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_le : forall a b : Z, 0 <= a -> 0 < b -> Z.rem a b <= a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_mod : forall a n : Z, 0 <= a -> 0 < n -> Z.rem (Z.rem a n) n = Z.rem a n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_mul : forall a b : Z, 0 <= a -> 0 < b -> Z.rem (a * b) b = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_mul_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> Z.rem a (b * c) = Z.rem a b + b * Z.rem (a ÷ b) c. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_same : forall a : Z, 0 < a -> Z.rem a a = 0. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_small : forall a b : Z, 0 <= a < b -> Z.rem a b = a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_small_iff : forall a b : Z, 0 <= a -> 0 < b -> Z.rem a b = a <-> a < b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mod_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> r = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_div_le : forall a b : Z, 0 <= a -> 0 < b -> b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_mod_distr_l : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> Z.rem (c * a) (c * b) = c * Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_mod_distr_r : forall a b c : Z, 0 <= a -> 0 < b -> 0 < c -> Z.rem (a * c) (b * c) = Z.rem a b * c. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_mod : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> Z.rem (a * b) n = Z.rem (Z.rem a n * Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_mod_idemp_l : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> Z.rem (Z.rem a n * b) n = Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_mod_idemp_r : forall a b n : Z, 0 <= a -> 0 <= b -> 0 < n -> Z.rem (a * Z.rem b n) n = Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma Z_Private_Div_NZQuot_mul_succ_div_gt : forall a b : Z, 0 <= a -> 0 < b -> a < b * Z.succ (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_Private_Div_Quot2Div_div_mod : forall a b : Z, b <> 0 -> a = b * (a ÷ b) + Z.rem a b. Proof. intros; nia. Qed.
+Z_Private_Div_Quot2Div_div_wd Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) Z.quot
+Lemma Z_Private_Div_Quot2Div_mod_bound_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= Z.rem a b < b. Proof. intros; nia. Qed.
+Z_Private_Div_Quot2Div_mod_wd Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) Z.rem
+Lemma Z_quot_0_l : forall a : Z, a <> 0 -> 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma Z_quot_0_r_ext : forall x y : Z, y = 0 -> x ÷ y = 0. Proof. intros; nia. Qed.
+Lemma Z_quot_1_l : forall a : Z, 1 < a -> 1 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma Z_quot_1_r : forall a : Z, a ÷ 1 = a. Proof. intros; nia. Qed.
+Lemma Zquot2_quot : forall n : Z, Z.quot2 n = n ÷ 2. Proof. intros; nia. Qed.
+Lemma Z_quot_abs : forall a b : Z, b <> 0 -> Z.abs a ÷ Z.abs b = Z.abs (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_quot_abs_l : forall a b : Z, b <> 0 -> Z.abs a ÷ b = Z.sgn a * (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_quot_abs_r : forall a b : Z, b <> 0 -> a ÷ Z.abs b = Z.sgn b * (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_quot_add : forall a b c : Z, c <> 0 -> 0 <= (a + b * c) * a -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma Z_quot_add_l : forall a b c : Z, b <> 0 -> 0 <= (a * b + c) * c -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_div : forall a b : Z, b <> 0 -> a ÷ b = Z.sgn a * Z.sgn b * (Z.abs a / Z.abs b). Proof. intros; nia. Qed.
+Lemma Z_quot_div_nonneg : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = a / b. Proof. intros; nia. Qed.
+Lemma Z_quot_exact : forall a b : Z, b <> 0 -> a = b * (a ÷ b) <-> Z.rem a b = 0. Proof. intros; nia. Qed.
+Lemma Z_quot_le_compat_l : forall p q r : Z, 0 <= p -> 0 < q <= r -> p ÷ r <= p ÷ q. Proof. intros; nia. Qed.
+Lemma Z_quot_le_lower_bound : forall a b q : Z, 0 < b -> b * q <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_le_mono : forall a b c : Z, 0 < c -> a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma Z_quot_le_upper_bound : forall a b q : Z, 0 < b -> a <= b * q -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma Z_quot_lt : forall a b : Z, 0 < a -> 1 < b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma Z_quot_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < b * q -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma Z_quot_mul_cancel_l : forall a b c : Z, b <> 0 -> c <> 0 -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_mul_cancel_r : forall a b c : Z, b <> 0 -> c <> 0 -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_mul : forall a b : Z, b <> 0 -> a * b ÷ b = a. Proof. intros; nia. Qed.
+Lemma Z_quot_mul_le : forall a b c : Z, 0 <= a -> 0 < b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_opp_l : forall a b : Z, b <> 0 -> - a ÷ b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_quot_opp_opp : forall a b : Z, b <> 0 -> - a ÷ - b = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_opp_r : forall a b : Z, b <> 0 -> a ÷ - b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_quot_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_quot : forall a b c : Z, b <> 0 -> c <> 0 -> a ÷ b ÷ c = a ÷ (b * c). Proof. intros; nia. Qed.
+Lemma Z_quot_rem' : forall a b : Z, a = b * (a ÷ b) + Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_quot_rem : forall a b : Z, b <> 0 -> a = b * (a ÷ b) + Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_quot_same : forall a : Z, a <> 0 -> a ÷ a = 1. Proof. intros; nia. Qed.
+Lemma Z_quot_small : forall a b : Z, 0 <= a < b -> a ÷ b = 0. Proof. intros; nia. Qed.
+Lemma Z_quot_small_iff : forall a b : Z, b <> 0 -> a ÷ b = 0 <-> Z.abs a < Z.abs b. Proof. intros; nia. Qed.
+Lemma Z_quot_str_pos : forall a b : Z, 0 < b <= a -> 0 < a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_unique_exact : forall a b q : Z, b <> 0 -> a = b * q -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma Z_quot_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Z_quot_wd Morphisms.Proper (Morphisms.respectful Z.eq (Morphisms.respectful Z.eq Z.eq)) Z.quot
+Lemma Zquot_Zeven_rem : forall a : Z, Z.even a = (Z.rem a 2 =? 0). Proof. intros; nia. Qed.
+Lemma Zquot_Z_mult_quot_ge : forall a b : Z, a <= 0 -> a <= b * (a ÷ b) <= 0. Proof. intros; nia. Qed.
+Lemma Zquot_Z_mult_quot_le : forall a b : Z, 0 <= a -> 0 <= b * (a ÷ b) <= a. Proof. intros; nia. Qed.
+Lemma Zquot_Zmult_rem_distr_l : forall a b c : Z, Z.rem (c * a) (c * b) = c * Z.rem a b. Proof. intros; nia. Qed.
+Lemma Zquot_Zmult_rem_distr_r : forall a b c : Z, Z.rem (a * c) (b * c) = Z.rem a b * c. Proof. intros; nia. Qed.
+Lemma Zquot_Zmult_rem : forall a b n : Z, Z.rem (a * b) n = Z.rem (Z.rem a n * Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma Zquot_Zmult_rem_idemp_l : forall a b n : Z, Z.rem (Z.rem a n * b) n = Z.rem (a * b) n. Proof. intros; nia. Qed.
+Lemma Zquot_Zmult_rem_idemp_r : forall a b n : Z, Z.rem (b * Z.rem a n) n = Z.rem (b * a) n. Proof. intros; nia. Qed.
+Lemma Zquot_Zodd_rem : forall a : Z, Z.odd a = negb (Z.rem a 2 =? 0). Proof. intros; nia. Qed.
+Lemma Zquot_Zplus_rem : forall a b n : Z, 0 <= a * b -> Z.rem (a + b) n = Z.rem (Z.rem a n + Z.rem b n) n. Proof. intros; nia. Qed.
+Lemma Zquot_Zplus_rem_idemp_l : forall a b n : Z, 0 <= a * b -> Z.rem (Z.rem a n + b) n = Z.rem (a + b) n. Proof. intros; nia. Qed.
+Lemma Zquot_Zplus_rem_idemp_r : forall a b n : Z, 0 <= a * b -> Z.rem (b + Z.rem a n) n = Z.rem (b + a) n. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_0_l : forall a : Z, 0 ÷ a = 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_0_r : forall a : Z, a ÷ 0 = 0. Proof. intros; nia. Qed.
+Lemma Zquot_Z_quot_exact_full : forall a b : Z, a = b * (a ÷ b) <-> Z.rem a b = 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_le_lower_bound : forall a b q : Z, 0 < b -> q * b <= a -> q <= a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_le_upper_bound : forall a b q : Z, 0 < b -> a <= q * b -> a ÷ b <= q. Proof. intros; nia. Qed.
+Lemma Zquot_Z_quot_lt : forall a b : Z, 0 < a -> 2 <= b -> a ÷ b < a. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_lt_upper_bound : forall a b q : Z, 0 <= a -> 0 < b -> a < q * b -> a ÷ b < q. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_mod_unique_full : forall a b q r : Z, Zquot.Remainder a b r -> a = b * q + r -> q = a ÷ b /\ r = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Zquot_Z_quot_monotone : forall a b c : Z, 0 <= c -> a <= b -> a ÷ c <= b ÷ c. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_mult_cancel_l : forall a b c : Z, c <> 0 -> c * a ÷ (c * b) = a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_mult_cancel_r : forall a b c : Z, c <> 0 -> a * c ÷ (b * c) = a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_mult_le : forall a b c : Z, 0 <= a -> 0 <= b -> 0 <= c -> c * (a ÷ b) <= c * a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_opp_l : forall a b : Z, - a ÷ b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_opp_opp : forall a b : Z, - a ÷ - b = a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_opp_r : forall a b : Z, a ÷ - b = - (a ÷ b). Proof. intros; nia. Qed.
+Lemma Zquot_Z_quot_plus : forall a b c : Z, 0 <= (a + b * c) * a -> c <> 0 -> (a + b * c) ÷ c = a ÷ c + b. Proof. intros; nia. Qed.
+Lemma Zquot_Z_quot_plus_l : forall a b c : Z, 0 <= (a * b + c) * c -> b <> 0 -> b <> 0 -> (a * b + c) ÷ b = a + c ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Z_quot_pos : forall a b : Z, 0 <= a -> 0 <= b -> 0 <= a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquotrem_Zdiv_eucl_pos : forall a b : Z, 0 <= a -> 0 < b -> a ÷ b = a / b /\ Z.rem a b = a mod b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_sgn : forall a b : Z, 0 <= Z.sgn (a ÷ b) * Z.sgn a * Z.sgn b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_unique_full : forall a b q r : Z, Zquot.Remainder a b r -> a = b * q + r -> q = a ÷ b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_Zdiv_pos : forall a b : Z, 0 <= a -> 0 <= b -> a ÷ b = a / b. Proof. intros; nia. Qed.
+Lemma Zquot_Zquot_Zquot : forall a b c : Z, a ÷ b ÷ c = a ÷ (b * c). Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_0_l : forall a : Z, Z.rem 0 a = 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_0_r : forall a : Z, Z.rem a 0 = a. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_divides : forall a b : Z, Z.rem a b = 0 <-> (exists c : Z, a = b * c). Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_even : forall a : Z, Z.rem a 2 = (if Z.even a then 0 else Z.sgn a). Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_le : forall a b : Z, 0 <= a -> 0 <= b -> Z.rem a b <= a. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_lt_neg : forall a b : Z, a <= 0 -> b <> 0 -> - Z.abs b < Z.rem a b <= 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_lt_neg_neg : forall a b : Z, a <= 0 -> b < 0 -> b < Z.rem a b <= 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_lt_neg_pos : forall a b : Z, a <= 0 -> 0 < b -> - b < Z.rem a b <= 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_lt_pos : forall a b : Z, 0 <= a -> b <> 0 -> 0 <= Z.rem a b < Z.abs b. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_lt_pos_neg : forall a b : Z, 0 <= a -> b < 0 -> 0 <= Z.rem a b < - b. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_lt_pos_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= Z.rem a b < b. Proof. intros; nia. Qed.
+Lemma Zquot_Z_rem_mult : forall a b : Z, Z.rem (a * b) b = 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_odd : forall a : Z, Z.rem a 2 = (if Z.odd a then Z.sgn a else 0). Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_opp_l : forall a b : Z, Z.rem (- a) b = - Z.rem a b. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_opp_opp : forall a b : Z, Z.rem (- a) (- b) = - Z.rem a b. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_opp_r : forall a b : Z, Z.rem a (- b) = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Zquot_Z_rem_plus : forall a b c : Z, 0 <= (a + b * c) * a -> Z.rem (a + b * c) c = Z.rem a c. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_rem : forall a n : Z, Z.rem (Z.rem a n) n = Z.rem a n. Proof. intros; nia. Qed.
+Lemma Zquot_Z_rem_same : forall a : Z, Z.rem a a = 0. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_sgn2 : forall a b : Z, 0 <= Z.rem a b * a. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_sgn : forall a b : Z, 0 <= Z.sgn (Z.rem a b) * Z.sgn a. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_unique_full : forall a b q r : Z, Zquot.Remainder a b r -> a = b * q + r -> r = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_Zmod_pos : forall a b : Z, 0 <= a -> 0 < b -> Z.rem a b = a mod b. Proof. intros; nia. Qed.
+Lemma Zquot_Zrem_Zmod_zero : forall a b : Z, b <> 0 -> Z.rem a b = 0 <-> a mod b = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_0_l : forall a : Z, a <> 0 -> Z.rem 0 a = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_0_r_ext : forall x y : Z, y = 0 -> Z.rem x y = x. Proof. intros; nia. Qed.
+Lemma Z_rem_1_l : forall a : Z, 1 < a -> Z.rem 1 a = 1. Proof. intros; nia. Qed.
+Lemma Z_rem_1_r : forall a : Z, Z.rem a 1 = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_abs : forall a b : Z, b <> 0 -> Z.rem (Z.abs a) (Z.abs b) = Z.abs (Z.rem a b). Proof. intros; nia. Qed.
+Lemma Z_rem_abs_l : forall a b : Z, b <> 0 -> Z.rem (Z.abs a) b = Z.abs (Z.rem a b). Proof. intros; nia. Qed.
+Lemma Z_rem_abs_r : forall a b : Z, b <> 0 -> Z.rem a (Z.abs b) = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_add : forall a b c : Z, c <> 0 -> 0 <= (a + b * c) * a -> Z.rem (a + b * c) c = Z.rem a c. Proof. intros; nia. Qed.
+Lemma Z_rem_bound_abs : forall a b : Z, b <> 0 -> Z.abs (Z.rem a b) < Z.abs b. Proof. intros; nia. Qed.
+Lemma Z_rem_bound_neg_neg : forall x y : Z, y < 0 -> x <= 0 -> y < Z.rem x y <= 0. Proof. intros; nia. Qed.
+Lemma Z_rem_bound_neg_pos : forall x y : Z, y < 0 -> 0 <= x -> 0 <= Z.rem x y < - y. Proof. intros; nia. Qed.
+Lemma Z_rem_bound_pos : forall a b : Z, 0 <= a -> 0 < b -> 0 <= Z.rem a b < b. Proof. intros; nia. Qed.
+Lemma Z_rem_bound_pos_neg : forall x y : Z, 0 < y -> x <= 0 -> - y < Z.rem x y <= 0. Proof. intros; nia. Qed.
+Lemma Z_rem_bound_pos_pos : forall x y : Z, 0 < y -> 0 <= x -> 0 <= Z.rem x y < y. Proof. intros; nia. Qed.
+Lemma Z_rem_eq : forall a b : Z, b <> 0 -> Z.rem a b = a - b * (a ÷ b). Proof. intros; nia. Qed.
+Lemma Z_rem_le : forall a b : Z, 0 <= a -> 0 < b -> Z.rem a b <= a. Proof. intros; nia. Qed.
+Lemma Z_rem_mod_eq_0 : forall a b : Z, b <> 0 -> Z.rem a b = 0 <-> a mod b = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_mod : forall a b : Z, b <> 0 -> Z.rem a b = Z.sgn a * (Z.abs a mod Z.abs b). Proof. intros; nia. Qed.
+Lemma Z_rem_mod_nonneg : forall a b : Z, 0 <= a -> 0 < b -> Z.rem a b = a mod b. Proof. intros; nia. Qed.
+Lemma Z_rem_mul : forall a b : Z, b <> 0 -> Z.rem (a * b) b = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_nonneg : forall a b : Z, b <> 0 -> 0 <= a -> 0 <= Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_nonpos : forall a b : Z, b <> 0 -> a <= 0 -> Z.rem a b <= 0. Proof. intros; nia. Qed.
+Lemma Z_rem_opp_l : forall a b : Z, b <> 0 -> Z.rem (- a) b = - Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_opp_l' : forall a b : Z, Z.rem (- a) b = - Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_opp_opp : forall a b : Z, b <> 0 -> Z.rem (- a) (- b) = - Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_opp_r : forall a b : Z, b <> 0 -> Z.rem a (- b) = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_opp_r' : forall a b : Z, Z.rem a (- b) = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_quot : forall a b : Z, b <> 0 -> Z.rem a b ÷ b = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_rem : forall a n : Z, n <> 0 -> Z.rem (Z.rem a n) n = Z.rem a n. Proof. intros; nia. Qed.
+Lemma Z_rem_same : forall a : Z, a <> 0 -> Z.rem a a = 0. Proof. intros; nia. Qed.
+Lemma Z_rem_sign : forall a b : Z, a <> 0 -> b <> 0 -> Z.sgn (Z.rem a b) <> - Z.sgn a. Proof. intros; nia. Qed.
+Lemma Z_rem_sign_mul : forall a b : Z, b <> 0 -> 0 <= Z.rem a b * a. Proof. intros; nia. Qed.
+Lemma Z_rem_sign_nz : forall a b : Z, b <> 0 -> Z.rem a b <> 0 -> Z.sgn (Z.rem a b) = Z.sgn a. Proof. intros; nia. Qed.
+Lemma Z_rem_small : forall a b : Z, 0 <= a < b -> Z.rem a b = a. Proof. intros; nia. Qed.
+Lemma Z_rem_small_iff : forall a b : Z, b <> 0 -> Z.rem a b = a <-> Z.abs a < Z.abs b. Proof. intros; nia. Qed.
+Lemma Z_rem_unique : forall a b q r : Z, 0 <= a -> 0 <= r < b -> a = b * q + r -> r = Z.rem a b. Proof. intros; nia. Qed.
+Lemma Z_rem_wd : Morphisms.Proper (Morphisms.respectful Z.eq (Morphisms.respectful Z.eq Z.eq)) Z.rem. Proof. intros; nia. Qed.
+*)
diff --git a/test-suite/success/NumeralNotations.v b/test-suite/success/NumeralNotations.v
index 47ef381270..7b857c70c5 100644
--- a/test-suite/success/NumeralNotations.v
+++ b/test-suite/success/NumeralNotations.v
@@ -300,3 +300,14 @@ Module Test16.
(** Ideally this should work, but it should definitely not anomaly *)
Fail Check let v := 0%test16 in v : Foo.
End Test16.
+
+Require Import Coq.Numbers.Cyclic.Int63.Int63.
+Module Test17.
+ (** Test int63 *)
+ Declare Scope test17_scope.
+ Delimit Scope test17_scope with test17.
+ Local Set Primitive Projections.
+ Record myint63 := of_int { to_int : int }.
+ Numeral Notation myint63 of_int to_int : test17_scope.
+ Check let v := 0%test17 in v : myint63.
+End Test17.
diff --git a/test-suite/success/Typeclasses.v b/test-suite/success/Typeclasses.v
index 9086621344..3888cafed3 100644
--- a/test-suite/success/Typeclasses.v
+++ b/test-suite/success/Typeclasses.v
@@ -14,7 +14,7 @@ Module onlyclasses.
Module RJung.
Class Foo (x : nat).
- Instance foo x : x = 2 -> Foo x.
+ Instance foo x : x = 2 -> Foo x := {}.
Hint Extern 0 (_ = _) => reflexivity : typeclass_instances.
Typeclasses eauto := debug.
Check (_ : Foo 2).
@@ -63,7 +63,7 @@ End RefineVsNoTceauto.
Module Leivantex2PR339.
(** Was a bug preventing to find hints associated with no pattern *)
Class Bar := {}.
- Instance bar1 (t:Type) : Bar.
+ Instance bar1 (t:Type) : Bar := {}.
Hint Extern 0 => exact True : typeclass_instances.
Typeclasses eauto := debug.
Goal Bar.
@@ -222,10 +222,10 @@ Module IterativeDeepening.
Class B.
Class C.
- Instance: B -> A | 0.
- Instance: C -> A | 0.
- Instance: C -> B -> A | 0.
- Instance: A -> A | 0.
+ Instance: B -> A | 0 := {}.
+ Instance: C -> A | 0 := {}.
+ Instance: C -> B -> A | 0 := {}.
+ Instance: A -> A | 0 := {}.
Goal C -> A.
intros.
diff --git a/test-suite/success/auto.v b/test-suite/success/auto.v
index 5477c83316..62a66daf7d 100644
--- a/test-suite/success/auto.v
+++ b/test-suite/success/auto.v
@@ -51,7 +51,7 @@ Qed.
Class B (A : Type).
Class I.
-Instance i : I.
+Instance i : I := {}.
Definition flip {A B C : Type} (f : A -> B -> C) := fun y x => f x y.
Class D (f : nat -> nat -> nat).
@@ -59,7 +59,7 @@ Definition ftest (x y : nat) := x + y.
Definition flipD (f : nat -> nat -> nat) : D f -> D (flip f).
Admitted.
Module Instnopat.
- Local Instance: B nat.
+ Local Instance: B nat := {}.
(* pattern_of_constr -> B nat *)
(* exact hint *)
Check (_ : B nat).
@@ -72,7 +72,7 @@ Module Instnopat.
eauto with typeclass_instances.
Qed.
- Local Instance: D ftest.
+ Local Instance: D ftest := {}.
Local Hint Resolve flipD | 0 : typeclass_instances.
(* pattern: D (flip _) *)
Fail Timeout 1 Check (_ : D _). (* loops applying flipD *)
@@ -80,7 +80,7 @@ Module Instnopat.
End Instnopat.
Module InstnopatApply.
- Local Instance: I -> B nat.
+ Local Instance: I -> B nat := {}.
(* pattern_of_constr -> B nat *)
(* apply hint *)
Check (_ : B nat).
@@ -116,7 +116,7 @@ Module InstPat.
Hint Extern 0 (D (flip _)) => apply flipD : typeclass_instances.
Module withftest.
- Local Instance: D ftest.
+ Local Instance: D ftest := {}.
Check (_ : D _).
(* D_instance_0 : D ftest *)
diff --git a/test-suite/success/bteauto.v b/test-suite/success/bteauto.v
index 730b367d60..cea7d92c0b 100644
--- a/test-suite/success/bteauto.v
+++ b/test-suite/success/bteauto.v
@@ -149,10 +149,10 @@ Module IterativeDeepening.
Class B.
Class C.
- Instance: B -> A | 0.
- Instance: C -> A | 0.
- Instance: C -> B -> A | 0.
- Instance: A -> A | 0.
+ Instance: B -> A | 0 := {}.
+ Instance: C -> A | 0 := {}.
+ Instance: C -> B -> A | 0 := {}.
+ Instance: A -> A | 0 := {}.
Goal C -> A.
intros.
diff --git a/test-suite/success/destruct.v b/test-suite/success/destruct.v
index d1d384659b..573912c7cd 100644
--- a/test-suite/success/destruct.v
+++ b/test-suite/success/destruct.v
@@ -263,7 +263,7 @@ Abort.
(* This one was working in 8.4 (because of full conv on closed arguments) *)
Class E.
-Instance a:E.
+Instance a:E := {}.
Goal forall h : E -> nat -> nat, h (id a) 0 = h a 0.
intros.
destruct (h _).
diff --git a/test-suite/success/eauto.v b/test-suite/success/eauto.v
index c44747379f..5b616ccc33 100644
--- a/test-suite/success/eauto.v
+++ b/test-suite/success/eauto.v
@@ -9,11 +9,11 @@
(************************************************************************)
Class A (A : Type).
- Instance an: A nat.
+ Instance an: A nat := {}.
Class B (A : Type) (a : A).
-Instance bn0: B nat 0.
-Instance bn1: B nat 1.
+Instance bn0: B nat 0 := {}.
+Instance bn1: B nat 1 := {}.
Goal A nat.
Proof.
@@ -39,7 +39,7 @@ Proof.
eexists. eexists. typeclasses eauto.
Defined.
-Instance ab: A bool. (* Backtrack on A instance *)
+Instance ab: A bool := {}. (* Backtrack on A instance *)
Goal exists (T : Type) (t : T), A T /\ B T t.
Proof.
eexists. eexists. typeclasses eauto.
@@ -51,7 +51,7 @@ Hint Extern 0 { x : ?A & _ } =>
unshelve class_apply @existT : typeclass_instances.
Existing Class sigT.
Set Typeclasses Debug.
-Instance can: C an 0.
+Instance can: C an 0 := {}.
(* Backtrack on instance implementation *)
Goal exists (T : Type) (t : T), { x : A T & C x t }.
Proof.
@@ -59,7 +59,7 @@ Proof.
Defined.
Class D T `(a: A T).
- Instance: D _ an.
+ Instance: D _ an := {}.
Goal exists (T : Type), { x : A T & D T x }.
Proof.
eexists. typeclasses eauto.
diff --git a/test-suite/success/setoid_test2.v b/test-suite/success/setoid_test2.v
index 79467e549c..351481b0b6 100644
--- a/test-suite/success/setoid_test2.v
+++ b/test-suite/success/setoid_test2.v
@@ -120,7 +120,7 @@ Axiom eqS1: S1 -> S1 -> Prop.
Axiom SetoidS1 : Setoid_Theory S1 eqS1.
Add Setoid S1 eqS1 SetoidS1 as S1setoid.
-Instance eqS1_default : DefaultRelation eqS1.
+Instance eqS1_default : DefaultRelation eqS1 := {}.
Axiom eqS1': S1 -> S1 -> Prop.
Axiom SetoidS1' : Setoid_Theory S1 eqS1'.
@@ -220,7 +220,7 @@ Axiom eqS1_test8: S1_test8 -> S1_test8 -> Prop.
Axiom SetoidS1_test8 : Setoid_Theory S1_test8 eqS1_test8.
Add Setoid S1_test8 eqS1_test8 SetoidS1_test8 as S1_test8setoid.
-Instance eqS1_test8_default : DefaultRelation eqS1_test8.
+Instance eqS1_test8_default : DefaultRelation eqS1_test8 := {}.
Axiom f_test8 : S2 -> S1_test8.
Add Morphism f_test8 with signature (eqS2 ==> eqS1_test8) as f_compat_test8. Admitted.
diff --git a/test-suite/tools/update-compat/run.sh b/test-suite/tools/update-compat/run.sh
index 02a2348450..61273c4f37 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 --cur-version=8.9 || exit $?
+dev/tools/update-compat.py --assert-unchanged --master || exit $?
diff --git a/theories/Bool/BoolEq.v b/theories/Bool/BoolEq.v
index 106a79e8c9..59a1b8da43 100644
--- a/theories/Bool/BoolEq.v
+++ b/theories/Bool/BoolEq.v
@@ -67,8 +67,8 @@ Section Bool_eq_dec.
Proof.
intros x y; case (exists_beq_eq x y).
intros b; case b; intro H.
- left; apply beq_eq; assumption.
- right; apply beq_false_not_eq; assumption.
+ - left; apply beq_eq; assumption.
+ - right; apply beq_false_not_eq; assumption.
Defined.
End Bool_eq_dec.
diff --git a/theories/Bool/IfProp.v b/theories/Bool/IfProp.v
index 6f99ea1da7..32ed7fe78d 100644
--- a/theories/Bool/IfProp.v
+++ b/theories/Bool/IfProp.v
@@ -45,6 +45,6 @@ Qed.
Lemma IfProp_sum : forall (A B:Prop) (b:bool), IfProp A B b -> {A} + {B}.
destruct b; intro H.
-left; inversion H; auto with bool.
-right; inversion H; auto with bool.
+- left; inversion H; auto with bool.
+- right; inversion H; auto with bool.
Qed.
diff --git a/theories/Classes/CMorphisms.v b/theories/Classes/CMorphisms.v
index 97510578ae..f9ca1bed29 100644
--- a/theories/Classes/CMorphisms.v
+++ b/theories/Classes/CMorphisms.v
@@ -164,7 +164,11 @@ Section Relations.
Lemma pointwise_pointwise {B} (R : crelation B) :
relation_equivalence (pointwise_relation R) (@eq A ==> R).
- Proof. intros. split. simpl_crelation. firstorder. Qed.
+ Proof.
+ intros. split.
+ - simpl_crelation.
+ - firstorder.
+ Qed.
(** Subcrelations induce a morphism on the identity. *)
@@ -265,8 +269,8 @@ Section GenericInstances.
Next Obligation.
Proof with auto.
assert(R x0 x0).
- transitivity y0... symmetry...
- transitivity (y x0)...
+ - transitivity y0... symmetry...
+ - transitivity (y x0)...
Qed.
Unset Strict Universe Declaration.
@@ -339,10 +343,11 @@ Section GenericInstances.
Next Obligation.
Proof with auto.
- split. intros ; transitivity x0...
- intros.
- transitivity y...
- symmetry...
+ split.
+ - intros ; transitivity x0...
+ - intros.
+ transitivity y...
+ symmetry...
Qed.
(** Every Transitive crelation induces a morphism by "pushing" an [R x y] on the left of an [R x z] proof to get an [R y z] goal. *)
@@ -364,9 +369,9 @@ Section GenericInstances.
Next Obligation.
Proof with auto.
split ; intros.
- transitivity x0... transitivity x... symmetry...
+ - transitivity x0... transitivity x... symmetry...
- transitivity y... transitivity y0... symmetry...
+ - transitivity y... transitivity y0... symmetry...
Qed.
Lemma symmetric_equiv_flip `(Symmetric A R) : relation_equivalence R (flip R).
@@ -397,8 +402,8 @@ Section GenericInstances.
intros A B R R' HRR' S S' HSS' f g.
unfold respectful , relation_equivalence in *; simpl in *.
split ; intros H x y Hxy.
- apply (fst (HSS' _ _)). apply H. now apply (snd (HRR' _ _)).
- apply (snd (HSS' _ _)). apply H. now apply (fst (HRR' _ _)).
+ - apply (fst (HSS' _ _)). apply H. now apply (snd (HRR' _ _)).
+ - apply (snd (HSS' _ _)). apply H. now apply (fst (HRR' _ _)).
Qed.
(** [R] is Reflexive, hence we can build the needed proof. *)
@@ -500,8 +505,8 @@ Instance proper_proper : Proper (relation_equivalence ==> eq ==> iffT) (@Proper
Proof.
intros A R R' HRR' x y <-. red in HRR'.
split ; red ; intros.
- now apply (fst (HRR' _ _)).
- now apply (snd (HRR' _ _)).
+ - now apply (fst (HRR' _ _)).
+ - now apply (snd (HRR' _ _)).
Qed.
Ltac proper_reflexive :=
@@ -636,9 +641,9 @@ intros.
apply proper_sym_arrow_iffT_2; auto with *.
intros x x' Hx y y' Hy Hr.
transitivity x.
-generalize (partial_order_equivalence x x'); compute; intuition.
-transitivity y; auto.
-generalize (partial_order_equivalence y y'); compute; intuition.
+- generalize (partial_order_equivalence x x'); compute; intuition.
+- transitivity y; auto.
+ generalize (partial_order_equivalence y y'); compute; intuition.
Qed.
(** From a [PartialOrder] to the corresponding [StrictOrder]:
@@ -649,13 +654,13 @@ Lemma PartialOrder_StrictOrder `(PartialOrder A eqA R) :
StrictOrder (relation_conjunction R (complement eqA)).
Proof.
split; compute.
-intros x (_,Hx). apply Hx, Equivalence_Reflexive.
-intros x y z (Hxy,Hxy') (Hyz,Hyz'). split.
-apply PreOrder_Transitive with y; assumption.
-intro Hxz.
-apply Hxy'.
-apply partial_order_antisym; auto.
-rewrite Hxz. auto.
+- intros x (_,Hx). apply Hx, Equivalence_Reflexive.
+- intros x y z (Hxy,Hxy') (Hyz,Hyz'). split.
+ + apply PreOrder_Transitive with y; assumption.
+ + intro Hxz.
+ apply Hxy'.
+ apply partial_order_antisym; auto.
+ rewrite Hxz. auto.
Qed.
(** From a [StrictOrder] to the corresponding [PartialOrder]:
@@ -667,12 +672,12 @@ Lemma StrictOrder_PreOrder
PreOrder (relation_disjunction R eqA).
Proof.
split.
-intros x. right. reflexivity.
-intros x y z [Hxy|Hxy] [Hyz|Hyz].
-left. transitivity y; auto.
-left. rewrite <- Hyz; auto.
-left. rewrite Hxy; auto.
-right. transitivity y; auto.
+- intros x. right. reflexivity.
+- intros x y z [Hxy|Hxy] [Hyz|Hyz].
+ + left. transitivity y; auto.
+ + left. rewrite <- Hyz; auto.
+ + left. rewrite Hxy; auto.
+ + right. transitivity y; auto.
Qed.
Hint Extern 4 (PreOrder (relation_disjunction _ _)) =>
diff --git a/theories/Classes/CRelationClasses.v b/theories/Classes/CRelationClasses.v
index bc821532fe..c014ecc7ab 100644
--- a/theories/Classes/CRelationClasses.v
+++ b/theories/Classes/CRelationClasses.v
@@ -177,6 +177,7 @@ Section Defs.
a rewrite crelation. *)
Global Instance equivalence_rewrite_crelation `(Equivalence eqA) : RewriteRelation eqA.
+ Defined.
(** Leibniz equality. *)
Section Leibniz.
@@ -195,7 +196,10 @@ End Defs.
(** Default rewrite crelations handled by [setoid_rewrite]. *)
Instance: RewriteRelation impl.
+Defined.
+
Instance: RewriteRelation iff.
+Defined.
(** Hints to drive the typeclass resolution avoiding loops
due to the use of full unification. *)
@@ -299,7 +303,8 @@ Section Binary.
fun R R' => forall x y, iffT (R x y) (R' x y).
Global Instance: RewriteRelation relation_equivalence.
-
+ Defined.
+
Definition relation_conjunction (R : crelation A) (R' : crelation A) : crelation A :=
fun x y => prod (R x y) (R' x y).
@@ -310,9 +315,11 @@ Section Binary.
Global Instance relation_equivalence_equivalence :
Equivalence relation_equivalence.
- Proof. split; red; unfold relation_equivalence, iffT. firstorder.
- firstorder.
- intros. specialize (X x0 y0). specialize (X0 x0 y0). firstorder.
+ Proof.
+ split; red; unfold relation_equivalence, iffT.
+ - firstorder.
+ - firstorder.
+ - intros. specialize (X x0 y0). specialize (X0 x0 y0). firstorder.
Qed.
Global Instance relation_implication_preorder : PreOrder (@subrelation A).
@@ -337,8 +344,11 @@ Section Binary.
Qed.
Lemma PartialOrder_inverse `(PartialOrder eqA R) : PartialOrder eqA (flip R).
- Proof. unfold flip; constructor; unfold flip. intros. apply H. apply symmetry. apply X.
- unfold relation_conjunction. intros [H1 H2]. apply H. constructor; assumption. Qed.
+ Proof.
+ unfold flip; constructor; unfold flip.
+ - intros. apply H. apply symmetry. apply X.
+ - unfold relation_conjunction. intros [H1 H2]. apply H. constructor; assumption.
+ Qed.
End Binary.
Hint Extern 3 (PartialOrder (flip _)) => class_apply PartialOrder_inverse : typeclass_instances.
diff --git a/theories/Classes/Morphisms.v b/theories/Classes/Morphisms.v
index 001b7dfdfd..a4fa537128 100644
--- a/theories/Classes/Morphisms.v
+++ b/theories/Classes/Morphisms.v
@@ -260,8 +260,8 @@ Section GenericInstances.
Next Obligation.
Proof with auto.
assert(R x0 x0).
- transitivity y0... symmetry...
- transitivity (y x0)...
+ - transitivity y0... symmetry...
+ - transitivity (y x0)...
Qed.
(** The complement of a relation conserves its proper elements. *)
@@ -344,10 +344,11 @@ Section GenericInstances.
Next Obligation.
Proof with auto.
- split. intros ; transitivity x0...
- intros.
- transitivity y...
- symmetry...
+ split.
+ - intros ; transitivity x0...
+ - intros.
+ transitivity y...
+ symmetry...
Qed.
(** Every Transitive relation induces a morphism by "pushing" an [R x y] on the left of an [R x z] proof to get an [R y z] goal. *)
@@ -369,9 +370,9 @@ Section GenericInstances.
Next Obligation.
Proof with auto.
split ; intros.
- transitivity x0... transitivity x... symmetry...
+ - transitivity x0... transitivity x... symmetry...
- transitivity y... transitivity y0... symmetry...
+ - transitivity y... transitivity y0... symmetry...
Qed.
Lemma symmetric_equiv_flip `(Symmetric A R) : relation_equivalence R (flip R).
@@ -403,15 +404,15 @@ Section GenericInstances.
unfold respectful, relation_equivalence, predicate_equivalence in * ; simpl in *.
split ; intros.
- rewrite <- H0.
- apply H1.
- rewrite H.
- assumption.
-
- rewrite H0.
- apply H1.
- rewrite <- H.
- assumption.
+ - rewrite <- H0.
+ apply H1.
+ rewrite H.
+ assumption.
+
+ - rewrite H0.
+ apply H1.
+ rewrite <- H.
+ assumption.
Qed.
(** [R] is Reflexive, hence we can build the needed proof. *)
@@ -514,10 +515,10 @@ Proof.
simpl_relation.
reduce in H.
split ; red ; intros.
- setoid_rewrite <- H.
- apply H0.
- setoid_rewrite H.
- apply H0.
+ - setoid_rewrite <- H.
+ apply H0.
+ - setoid_rewrite H.
+ apply H0.
Qed.
Ltac proper_reflexive :=
@@ -574,8 +575,8 @@ Proof.
unfold relation_equivalence in *.
unfold predicate_equivalence in *. simpl in *.
unfold respectful. unfold flip in *. firstorder.
- apply NB. apply H. apply NA. apply H0.
- apply NB. apply H. apply NA. apply H0.
+ - apply NB. apply H. apply NA. apply H0.
+ - apply NB. apply H. apply NA. apply H0.
Qed.
Ltac normalizes :=
@@ -642,9 +643,9 @@ intros.
apply proper_sym_impl_iff_2; auto with *.
intros x x' Hx y y' Hy Hr.
transitivity x.
-generalize (partial_order_equivalence x x'); compute; intuition.
-transitivity y; auto.
-generalize (partial_order_equivalence y y'); compute; intuition.
+- generalize (partial_order_equivalence x x'); compute; intuition.
+- transitivity y; auto.
+ generalize (partial_order_equivalence y y'); compute; intuition.
Qed.
(** From a [PartialOrder] to the corresponding [StrictOrder]:
@@ -655,13 +656,13 @@ Lemma PartialOrder_StrictOrder `(PartialOrder A eqA R) :
StrictOrder (relation_conjunction R (complement eqA)).
Proof.
split; compute.
-intros x (_,Hx). apply Hx, Equivalence_Reflexive.
-intros x y z (Hxy,Hxy') (Hyz,Hyz'). split.
-apply PreOrder_Transitive with y; assumption.
-intro Hxz.
-apply Hxy'.
-apply partial_order_antisym; auto.
-rewrite Hxz; auto.
+- intros x (_,Hx). apply Hx, Equivalence_Reflexive.
+- intros x y z (Hxy,Hxy') (Hyz,Hyz'). split.
+ + apply PreOrder_Transitive with y; assumption.
+ + intro Hxz.
+ apply Hxy'.
+ apply partial_order_antisym; auto.
+ rewrite Hxz; auto.
Qed.
@@ -674,12 +675,12 @@ Lemma StrictOrder_PreOrder
PreOrder (relation_disjunction R eqA).
Proof.
split.
-intros x. right. reflexivity.
-intros x y z [Hxy|Hxy] [Hyz|Hyz].
-left. transitivity y; auto.
-left. rewrite <- Hyz; auto.
-left. rewrite Hxy; auto.
-right. transitivity y; auto.
+- intros x. right. reflexivity.
+- intros x y z [Hxy|Hxy] [Hyz|Hyz].
+ + left. transitivity y; auto.
+ + left. rewrite <- Hyz; auto.
+ + left. rewrite Hxy; auto.
+ + right. transitivity y; auto.
Qed.
Hint Extern 4 (PreOrder (relation_disjunction _ _)) =>
diff --git a/theories/Classes/Morphisms_Prop.v b/theories/Classes/Morphisms_Prop.v
index 8881fda577..efb85aa341 100644
--- a/theories/Classes/Morphisms_Prop.v
+++ b/theories/Classes/Morphisms_Prop.v
@@ -85,10 +85,12 @@ Qed.
Instance Acc_rel_morphism {A:Type} :
Proper (relation_equivalence ==> Logic.eq ==> iff) (@Acc A).
Proof.
- apply proper_sym_impl_iff_2. red; now symmetry. red; now symmetry.
- intros R R' EQ a a' Ha WF. subst a'.
- induction WF as [x _ WF']. constructor.
- intros y Ryx. now apply WF', EQ.
+ apply proper_sym_impl_iff_2.
+ - red; now symmetry.
+ - red; now symmetry.
+ - intros R R' EQ a a' Ha WF. subst a'.
+ induction WF as [x _ WF']. constructor.
+ intros y Ryx. now apply WF', EQ.
Qed.
(** Equivalent relations are simultaneously well-founded or not *)
diff --git a/theories/Classes/RelationClasses.v b/theories/Classes/RelationClasses.v
index 4b97d75cea..440b317573 100644
--- a/theories/Classes/RelationClasses.v
+++ b/theories/Classes/RelationClasses.v
@@ -171,6 +171,7 @@ Section Defs.
a rewrite relation. *)
Global Instance equivalence_rewrite_relation `(Equivalence eqA) : RewriteRelation eqA.
+ Defined.
(** Leibniz equality. *)
Section Leibniz.
@@ -189,7 +190,9 @@ End Defs.
(** Default rewrite relations handled by [setoid_rewrite]. *)
Instance: RewriteRelation impl.
+Defined.
Instance: RewriteRelation iff.
+Defined.
(** Hints to drive the typeclass resolution avoiding loops
due to the use of full unification. *)
@@ -404,9 +407,10 @@ Program Instance predicate_equivalence_equivalence :
Qed.
Next Obligation.
fold pointwise_lifting.
- induction l. firstorder.
- intros. simpl in *. pose (IHl (x x0) (y x0) (z x0)).
- firstorder.
+ induction l.
+ - firstorder.
+ - intros. simpl in *. pose (IHl (x x0) (y x0) (z x0)).
+ firstorder.
Qed.
Program Instance predicate_implication_preorder :
@@ -415,9 +419,10 @@ Program Instance predicate_implication_preorder :
induction l ; firstorder.
Qed.
Next Obligation.
- induction l. firstorder.
- unfold predicate_implication in *. simpl in *.
- intro. pose (IHl (x x0) (y x0) (z x0)). firstorder.
+ induction l.
+ - firstorder.
+ - unfold predicate_implication in *. simpl in *.
+ intro. pose (IHl (x x0) (y x0) (z x0)). firstorder.
Qed.
(** We define the various operations which define the algebra on binary relations,
@@ -430,6 +435,7 @@ Section Binary.
@predicate_equivalence (_::_::Tnil).
Global Instance: RewriteRelation relation_equivalence.
+ Defined.
Definition relation_conjunction (R : relation A) (R' : relation A) : relation A :=
@predicate_intersection (A::A::Tnil) R R'.
diff --git a/theories/Classes/RelationPairs.v b/theories/Classes/RelationPairs.v
index 3e6358c8f3..341dacd4b2 100644
--- a/theories/Classes/RelationPairs.v
+++ b/theories/Classes/RelationPairs.v
@@ -62,7 +62,10 @@ Class Measure {A B} (f : A -> B).
(** Standard measures. *)
Instance fst_measure : @Measure (A * B) A Fst.
+Defined.
+
Instance snd_measure : @Measure (A * B) B Snd.
+Defined.
(** We define a product relation over [A*B]: each components should
satisfy the corresponding initial relation. *)
diff --git a/theories/Classes/SetoidTactics.v b/theories/Classes/SetoidTactics.v
index 3fab3c5a07..94920f74ec 100644
--- a/theories/Classes/SetoidTactics.v
+++ b/theories/Classes/SetoidTactics.v
@@ -41,6 +41,7 @@ Definition default_relation `{DefaultRelation A R} := R.
(lowest priority). *)
Instance equivalence_default `(Equivalence A R) : DefaultRelation R | 4.
+Defined.
(** The setoid_replace tactics in Ltac, defined in terms of default relations
and the setoid_rewrite tactic. *)
diff --git a/theories/Compat/Coq810.v b/theories/Compat/Coq810.v
new file mode 100644
index 0000000000..f10201661e
--- /dev/null
+++ b/theories/Compat/Coq810.v
@@ -0,0 +1,11 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(** Compatibility file for making Coq act similar to Coq v8.10 *)
diff --git a/theories/Compat/Coq88.v b/theories/Compat/Coq88.v
index 989072940a..e4a8df1e93 100644
--- a/theories/Compat/Coq88.v
+++ b/theories/Compat/Coq88.v
@@ -20,9 +20,11 @@ Require Coq.Strings.Ascii Coq.Strings.String.
Export String.StringSyntax Ascii.AsciiSyntax.
Require Coq.ZArith.BinIntDef Coq.PArith.BinPosDef Coq.NArith.BinNatDef.
Require Coq.Reals.Rdefinitions.
+Require Coq.Numbers.Cyclic.Int63.Int63.
Require Coq.Numbers.Cyclic.Int31.Int31.
Declare ML Module "r_syntax_plugin".
-Declare ML Module "int31_syntax_plugin".
+Declare ML Module "int63_syntax_plugin".
Numeral Notation BinNums.Z BinIntDef.Z.of_int BinIntDef.Z.to_int : Z_scope.
Numeral Notation BinNums.positive BinPosDef.Pos.of_int BinPosDef.Pos.to_int : positive_scope.
Numeral Notation BinNums.N BinNatDef.N.of_int BinNatDef.N.to_int : N_scope.
+Numeral Notation Int31.int31 Int31.phi_inv_nonneg Int31.phi : int31_scope.
diff --git a/theories/Compat/Coq89.v b/theories/Compat/Coq89.v
index decb5c7519..05d63d9a47 100644
--- a/theories/Compat/Coq89.v
+++ b/theories/Compat/Coq89.v
@@ -11,5 +11,7 @@
(** Compatibility file for making Coq act similar to Coq v8.9 *)
Local Set Warnings "-deprecated".
+Require Export Coq.Compat.Coq810.
+
Unset Private Polymorphic Universes.
Set Refine Instance Mode.
diff --git a/theories/Init/Decimal.v b/theories/Init/Decimal.v
index 537400fb05..3d4b3d0568 100644
--- a/theories/Init/Decimal.v
+++ b/theories/Init/Decimal.v
@@ -40,7 +40,7 @@ Notation zero := (D0 Nil).
(** For signed integers, we use two constructors [Pos] and [Neg]. *)
-Inductive int := Pos (d:uint) | Neg (d:uint).
+Variant int := Pos (d:uint) | Neg (d:uint).
Declare Scope dec_uint_scope.
Delimit Scope dec_uint_scope with uint.
@@ -50,6 +50,9 @@ Declare Scope dec_int_scope.
Delimit Scope dec_int_scope with int.
Bind Scope dec_int_scope with int.
+Register uint as num.uint.type.
+Register int as num.int.type.
+
(** This representation favors simplicity over canonicity.
For normalizing numbers, we need to remove head zero digits,
and choose our canonical representation of 0 (here [D0 Nil]
diff --git a/theories/Init/Logic.v b/theories/Init/Logic.v
index 1db0a8e1b5..b607be4f94 100644
--- a/theories/Init/Logic.v
+++ b/theories/Init/Logic.v
@@ -383,6 +383,11 @@ Section Logic_lemmas.
Register eq_trans as core.eq.trans.
+ Theorem eq_trans_r : x = y -> z = y -> x = z.
+ Proof.
+ destruct 2; trivial.
+ Defined.
+
Theorem f_equal : x = y -> f x = f y.
Proof.
destruct 1; trivial.
@@ -695,8 +700,8 @@ Proof.
- intros (x,(Hx,Huni)); split.
+ exists x; assumption.
+ intros x' x'' Hx' Hx''; transitivity x.
- symmetry; auto.
- auto.
+ * symmetry; auto.
+ * auto.
Qed.
Lemma forall_exists_unique_domain_coincide :
diff --git a/theories/Init/Prelude.v b/theories/Init/Prelude.v
index 5e29f854e8..81268a87ad 100644
--- a/theories/Init/Prelude.v
+++ b/theories/Init/Prelude.v
@@ -38,7 +38,7 @@ Numeral Notation Decimal.int Decimal.int_of_int Decimal.int_of_int
: dec_int_scope.
(* Parsing / printing of [nat] numbers *)
-Numeral Notation nat Nat.of_uint Nat.to_uint : nat_scope (abstract after 5000).
+Numeral Notation nat Nat.of_uint Nat.to_uint : nat_scope (abstract after 5001).
(* Printing/Parsing of bytes *)
Export Byte.ByteSyntaxNotations.
diff --git a/theories/Init/Specif.v b/theories/Init/Specif.v
index cfba2bae69..e5d63c547d 100644
--- a/theories/Init/Specif.v
+++ b/theories/Init/Specif.v
@@ -765,8 +765,9 @@ Section Dependent_choice_lemmas.
intros H x0.
set (f:=fix f n := match n with O => x0 | S n' => proj1_sig (H (f n')) end).
exists f.
- split. reflexivity.
- induction n; simpl; apply proj2_sig.
+ split.
+ - reflexivity.
+ - induction n; simpl; apply proj2_sig.
Defined.
End Dependent_choice_lemmas.
diff --git a/theories/Init/Tactics.v b/theories/Init/Tactics.v
index 8df533e743..af4632161e 100644
--- a/theories/Init/Tactics.v
+++ b/theories/Init/Tactics.v
@@ -202,13 +202,17 @@ Set Implicit Arguments.
Lemma decide_left : forall (C:Prop) (decide:{C}+{~C}),
C -> forall P:{C}+{~C}->Prop, (forall H:C, P (left _ H)) -> P decide.
Proof.
-intros; destruct decide. apply H0. contradiction.
+ intros; destruct decide.
+ - apply H0.
+ - contradiction.
Qed.
Lemma decide_right : forall (C:Prop) (decide:{C}+{~C}),
~C -> forall P:{C}+{~C}->Prop, (forall H:~C, P (right _ H)) -> P decide.
Proof.
-intros; destruct decide. contradiction. apply H0.
+ intros; destruct decide.
+ - contradiction.
+ - apply H0.
Qed.
Tactic Notation "decide" constr(lemma) "with" constr(H) :=
diff --git a/theories/Lists/StreamMemo.v b/theories/Lists/StreamMemo.v
index d93816e9ff..419a0be49c 100644
--- a/theories/Lists/StreamMemo.v
+++ b/theories/Lists/StreamMemo.v
@@ -118,16 +118,16 @@ intros n; unfold dmemo_get, dmemo_list.
rewrite (memo_get_correct memo_val mf n); simpl.
case (is_eq n n); simpl; auto; intros e.
assert (e = eq_refl n).
- apply eq_proofs_unicity.
- induction x as [| x Hx]; destruct y as [| y].
- left; auto.
- right; intros HH; discriminate HH.
- right; intros HH; discriminate HH.
- case (Hx y).
- intros HH; left; case HH; auto.
- intros HH; right; intros HH1; case HH.
- injection HH1; auto.
-rewrite H; auto.
+- apply eq_proofs_unicity.
+ induction x as [| x Hx]; destruct y as [| y].
+ + left; auto.
+ + right; intros HH; discriminate HH.
+ + right; intros HH; discriminate HH.
+ + case (Hx y).
+ * intros HH; left; case HH; auto.
+ * intros HH; right; intros HH1; case HH.
+ injection HH1; auto.
+- rewrite H; auto.
Qed.
(** Finally, a version with both dependency and iterator *)
@@ -145,19 +145,19 @@ Theorem dimemo_get_correct: forall n, dmemo_get n dimemo_list = f n.
Proof.
intros n; unfold dmemo_get, dimemo_list.
rewrite (imemo_get_correct memo_val mf mg); simpl.
-case (is_eq n n); simpl; auto; intros e.
-assert (e = eq_refl n).
- apply eq_proofs_unicity.
- induction x as [| x Hx]; destruct y as [| y].
- left; auto.
- right; intros HH; discriminate HH.
- right; intros HH; discriminate HH.
- case (Hx y).
- intros HH; left; case HH; auto.
- intros HH; right; intros HH1; case HH.
- injection HH1; auto.
-rewrite H; auto.
-intros n1; unfold mf; rewrite Hg_correct; auto.
+- case (is_eq n n); simpl; auto; intros e.
+ assert (e = eq_refl n).
+ + apply eq_proofs_unicity.
+ induction x as [| x Hx]; destruct y as [| y].
+ * left; auto.
+ * right; intros HH; discriminate HH.
+ * right; intros HH; discriminate HH.
+ * case (Hx y).
+ -- intros HH; left; case HH; auto.
+ -- intros HH; right; intros HH1; case HH.
+ injection HH1; auto.
+ + rewrite H; auto.
+- intros n1; unfold mf; rewrite Hg_correct; auto.
Qed.
End DependentMemoFunction.
diff --git a/theories/Lists/Streams.v b/theories/Lists/Streams.v
index a03799959e..4503b3b643 100644
--- a/theories/Lists/Streams.v
+++ b/theories/Lists/Streams.v
@@ -92,20 +92,20 @@ Qed.
Theorem sym_EqSt : forall s1 s2:Stream, EqSt s1 s2 -> EqSt s2 s1.
coinduction Eq_sym.
-case H; intros; symmetry ; assumption.
-case H; intros; assumption.
++ case H; intros; symmetry ; assumption.
++ case H; intros; assumption.
Qed.
Theorem trans_EqSt :
forall s1 s2 s3:Stream, EqSt s1 s2 -> EqSt s2 s3 -> EqSt s1 s3.
coinduction Eq_trans.
-transitivity (hd s2).
-case H; intros; assumption.
-case H0; intros; assumption.
-apply (Eq_trans (tl s1) (tl s2) (tl s3)).
-case H; trivial with datatypes.
-case H0; trivial with datatypes.
+- transitivity (hd s2).
+ + case H; intros; assumption.
+ + case H0; intros; assumption.
+- apply (Eq_trans (tl s1) (tl s2) (tl s3)).
+ + case H; trivial with datatypes.
+ + case H0; trivial with datatypes.
Qed.
(** The definition given is equivalent to require the elements at each
@@ -114,20 +114,20 @@ Qed.
Theorem eqst_ntheq :
forall (n:nat) (s1 s2:Stream), EqSt s1 s2 -> Str_nth n s1 = Str_nth n s2.
unfold Str_nth; simple induction n.
-intros s1 s2 H; case H; trivial with datatypes.
-intros m hypind.
-simpl.
-intros s1 s2 H.
-apply hypind.
-case H; trivial with datatypes.
+- intros s1 s2 H; case H; trivial with datatypes.
+- intros m hypind.
+ simpl.
+ intros s1 s2 H.
+ apply hypind.
+ case H; trivial with datatypes.
Qed.
Theorem ntheq_eqst :
forall s1 s2:Stream,
(forall n:nat, Str_nth n s1 = Str_nth n s2) -> EqSt s1 s2.
coinduction Equiv2.
-apply (H 0).
-intros n; apply (H (S n)).
+- apply (H 0).
+- intros n; apply (H (S n)).
Qed.
Section Stream_Properties.
@@ -150,11 +150,11 @@ CoInductive ForAll (x: Stream) : Prop :=
Lemma ForAll_Str_nth_tl : forall m x, ForAll x -> ForAll (Str_nth_tl m x).
Proof.
induction m.
- tauto.
-intros x [_ H].
-simpl.
-apply IHm.
-assumption.
+- tauto.
+- intros x [_ H].
+ simpl.
+ apply IHm.
+ assumption.
Qed.
Section Co_Induction_ForAll.
@@ -179,10 +179,10 @@ CoFixpoint map (s:Stream A) : Stream B := Cons (f (hd s)) (map (tl s)).
Lemma Str_nth_tl_map : forall n s, Str_nth_tl n (map s)= map (Str_nth_tl n s).
Proof.
induction n.
-reflexivity.
-simpl.
-intros s.
-apply IHn.
+- reflexivity.
+- simpl.
+ intros s.
+ apply IHn.
Qed.
Lemma Str_nth_map : forall n s, Str_nth n (map s)= f (Str_nth n s).
@@ -228,11 +228,11 @@ Lemma Str_nth_tl_zipWith : forall n (a:Stream A) (b:Stream B),
Str_nth_tl n (zipWith a b)= zipWith (Str_nth_tl n a) (Str_nth_tl n b).
Proof.
induction n.
-reflexivity.
-intros [x xs] [y ys].
-unfold Str_nth in *.
-simpl in *.
-apply IHn.
+- reflexivity.
+- intros [x xs] [y ys].
+ unfold Str_nth in *.
+ simpl in *.
+ apply IHn.
Qed.
Lemma Str_nth_zipWith : forall n (a:Stream A) (b:Stream B), Str_nth n (zipWith a
diff --git a/theories/Logic/Berardi.v b/theories/Logic/Berardi.v
index ed4d69ab02..86894cd1f2 100644
--- a/theories/Logic/Berardi.v
+++ b/theories/Logic/Berardi.v
@@ -88,8 +88,8 @@ Lemma L1 : forall A B:Prop, retract_cond (pow A) (pow B).
Proof.
intros A B.
destruct (EM (retract (pow A) (pow B))) as [(f0,g0,e) | hf].
- exists f0 g0; trivial.
- exists (fun (x:pow A) (y:B) => F) (fun (x:pow B) (y:A) => F); intros;
+- exists f0 g0; trivial.
+- exists (fun (x:pow A) (y:B) => F) (fun (x:pow B) (y:A) => F); intros;
destruct hf; auto.
Qed.
@@ -130,9 +130,9 @@ Proof.
unfold R at 1.
unfold g.
rewrite AC.
-trivial.
-exists (fun x:pow U => x) (fun x:pow U => x).
-trivial.
+- trivial.
+- exists (fun x:pow U => x) (fun x:pow U => x).
+ trivial.
Qed.
@@ -141,11 +141,11 @@ Proof.
generalize not_has_fixpoint.
unfold Not_b.
apply AC_IF.
-intros is_true is_false.
-elim is_true; elim is_false; trivial.
+- intros is_true is_false.
+ elim is_true; elim is_false; trivial.
-intros not_true is_true.
-elim not_true; trivial.
+- intros not_true is_true.
+ elim not_true; trivial.
Qed.
diff --git a/theories/Logic/EqdepFacts.v b/theories/Logic/EqdepFacts.v
index 8e59941f37..b930388d13 100644
--- a/theories/Logic/EqdepFacts.v
+++ b/theories/Logic/EqdepFacts.v
@@ -372,8 +372,7 @@ Proof.
rewrite (UIP_refl y).
intros z.
assert (UIP:forall y' y'' : x = x, y' = y'').
- { intros. apply eq_trans with (eq_refl x). apply UIP_refl.
- symmetry. apply UIP_refl. }
+ { intros. apply eq_trans_r with (eq_refl x); apply UIP_refl. }
transitivity (eq_trans (eq_trans (UIP (eq_refl x) (eq_refl x)) z)
(eq_sym (UIP (eq_refl x) (eq_refl x)))).
- destruct z. destruct (UIP _ _). reflexivity.
diff --git a/theories/Logic/Eqdep_dec.v b/theories/Logic/Eqdep_dec.v
index 4e8b48af9f..3babc9437b 100644
--- a/theories/Logic/Eqdep_dec.v
+++ b/theories/Logic/Eqdep_dec.v
@@ -66,9 +66,9 @@ Section EqdepDec.
intros.
unfold nu.
destruct (eq_dec y) as [Heq|Hneq].
- reflexivity.
+ - reflexivity.
- case Hneq; trivial.
+ - case Hneq; trivial.
Qed.
@@ -118,15 +118,15 @@ Section EqdepDec.
Proof.
intros.
cut (proj (ex_intro P x y) y = proj (ex_intro P x y') y).
- simpl.
- destruct (eq_dec x) as [Heq|Hneq].
- elim Heq using K_dec_on; trivial.
+ - simpl.
+ destruct (eq_dec x) as [Heq|Hneq].
+ + elim Heq using K_dec_on; trivial.
- intros.
- case Hneq; trivial.
+ + intros.
+ case Hneq; trivial.
- case H.
- reflexivity.
+ - case H.
+ reflexivity.
Qed.
End EqdepDec.
@@ -163,8 +163,8 @@ Theorem K_dec_type :
Proof.
intros A eq_dec x P H p.
elim p using K_dec; intros.
- case (eq_dec x0 y); [left|right]; assumption.
- trivial.
+ - case (eq_dec x0 y); [left|right]; assumption.
+ - trivial.
Qed.
Theorem K_dec_set :
@@ -260,8 +260,8 @@ Module DecidableEqDep (M:DecidableType).
Proof.
intros.
apply inj_right_pair with (A:=U).
- intros x0 y0; case (eq_dec x0 y0); [left|right]; assumption.
- assumption.
+ - intros x0 y0; case (eq_dec x0 y0); [left|right]; assumption.
+ - assumption.
Qed.
End DecidableEqDep.
diff --git a/theories/Logic/JMeq.v b/theories/Logic/JMeq.v
index 3914f44a2c..11897b6cb1 100644
--- a/theories/Logic/JMeq.v
+++ b/theories/Logic/JMeq.v
@@ -135,10 +135,10 @@ Proof.
exists bool. exists (fun _ => True). exists true. exists false.
exists I. exists I.
split.
-trivial.
-intro H.
-assert (true=false) by (destruct H; reflexivity).
-discriminate.
+- trivial.
+- intro H.
+ assert (true=false) by (destruct H; reflexivity).
+ discriminate.
Qed.
(** However, when the dependencies are equal, [JMeq (P p) x (P q) y]
diff --git a/theories/Numbers/BinNums.v b/theories/Numbers/BinNums.v
index ef2c688759..247827597a 100644
--- a/theories/Numbers/BinNums.v
+++ b/theories/Numbers/BinNums.v
@@ -29,6 +29,7 @@ Bind Scope positive_scope with positive.
Arguments xO _%positive.
Arguments xI _%positive.
+Register positive as num.pos.type.
Register xI as num.pos.xI.
Register xO as num.pos.xO.
Register xH as num.pos.xH.
diff --git a/theories/Numbers/Cyclic/Abstract/DoubleType.v b/theories/Numbers/Cyclic/Abstract/DoubleType.v
index b6441bb76a..9547a642df 100644
--- a/theories/Numbers/Cyclic/Abstract/DoubleType.v
+++ b/theories/Numbers/Cyclic/Abstract/DoubleType.v
@@ -12,7 +12,7 @@
Set Implicit Arguments.
-Require Import ZArith.
+Require Import BinInt.
Local Open Scope Z_scope.
Definition base digits := Z.pow 2 (Zpos digits).
@@ -23,7 +23,7 @@ Section Carry.
Variable A : Type.
#[universes(template)]
- Inductive carry :=
+ Variant carry :=
| C0 : A -> carry
| C1 : A -> carry.
@@ -46,7 +46,7 @@ Section Zn2Z.
*)
#[universes(template)]
- Inductive zn2z :=
+ Variant zn2z :=
| W0 : zn2z
| WW : znz -> znz -> zn2z.
diff --git a/theories/Numbers/Cyclic/Int31/Cyclic31.v b/theories/Numbers/Cyclic/Int31/Cyclic31.v
index 4a1f24b95e..4b0bda3d44 100644
--- a/theories/Numbers/Cyclic/Int31/Cyclic31.v
+++ b/theories/Numbers/Cyclic/Int31/Cyclic31.v
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+(** This library has been deprecated since Coq version 8.10. *)
+
(** * Int31 numbers defines indeed a cyclic structure : Z/(2^31)Z *)
(**
@@ -1274,7 +1276,7 @@ Section Int31_Specs.
Qed.
Lemma spec_add_carry :
- forall x y, [|x+y+1|] = ([|x|] + [|y|] + 1) mod wB.
+ forall x y, [|x+y+1|] = ([|x|] + [|y|] + 1) mod wB.
Proof.
unfold add31; intros.
repeat rewrite phi_phi_inv.
@@ -1776,7 +1778,7 @@ Section Int31_Specs.
Qed.
Lemma spec_head0 : forall x, 0 < [|x|] ->
- wB/ 2 <= 2 ^ ([|head031 x|]) * [|x|] < wB.
+ wB/ 2 <= 2 ^ ([|head031 x|]) * [|x|] < wB.
Proof.
intros.
rewrite head031_equiv.
diff --git a/theories/Numbers/Cyclic/Int31/Int31.v b/theories/Numbers/Cyclic/Int31/Int31.v
index ce540775e3..b9185c9ca0 100644
--- a/theories/Numbers/Cyclic/Int31/Int31.v
+++ b/theories/Numbers/Cyclic/Int31/Int31.v
@@ -10,6 +10,8 @@
(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *)
(************************************************************************)
+(** This library has been deprecated since Coq version 8.10. *)
+
Require Import NaryFunctions.
Require Import Wf_nat.
Require Export ZArith.
@@ -44,18 +46,11 @@ Definition digits31 t := Eval compute in nfun digits size t.
Inductive int31 : Type := I31 : digits31 int31.
-(* spiwack: Registration of the type of integers, so that the matchs in
- the functions below perform dynamic decompilation (otherwise some segfault
- occur when they are applied to one non-closed term and one closed term). *)
-Register digits as int31.bits.
-Register int31 as int31.type.
-
Scheme int31_ind := Induction for int31 Sort Prop.
Scheme int31_rec := Induction for int31 Sort Set.
Scheme int31_rect := Induction for int31 Sort Type.
Declare Scope int31_scope.
-Declare ML Module "int31_syntax_plugin".
Delimit Scope int31_scope with int31.
Bind Scope int31_scope with int31.
Local Open Scope int31_scope.
@@ -208,6 +203,13 @@ Definition phi_inv : Z -> int31 := fun n =>
| Zneg p => incr (complement_negative p)
end.
+(** [phi_inv_nonneg] returns [None] if the [Z] is negative; this matches the old behavior of parsing int31 numerals *)
+Definition phi_inv_nonneg : Z -> option int31 := fun n =>
+ match n with
+ | Zneg _ => None
+ | _ => Some (phi_inv n)
+ end.
+
(** [phi_inv2] is similar to [phi_inv] but returns a double word
[zn2z int31] *)
@@ -351,22 +353,6 @@ Definition lor31 n m := phi_inv (Z.lor (phi n) (phi m)).
Definition land31 n m := phi_inv (Z.land (phi n) (phi m)).
Definition lxor31 n m := phi_inv (Z.lxor (phi n) (phi m)).
-Register add31 as int31.plus.
-Register add31c as int31.plusc.
-Register add31carryc as int31.pluscarryc.
-Register sub31 as int31.minus.
-Register sub31c as int31.minusc.
-Register sub31carryc as int31.minuscarryc.
-Register mul31 as int31.times.
-Register mul31c as int31.timesc.
-Register div3121 as int31.div21.
-Register div31 as int31.diveucl.
-Register compare31 as int31.compare.
-Register addmuldiv31 as int31.addmuldiv.
-Register lor31 as int31.lor.
-Register land31 as int31.land.
-Register lxor31 as int31.lxor.
-
Definition lnot31 n := lxor31 Tn n.
Definition ldiff31 n m := land31 n (lnot31 m).
@@ -491,5 +477,4 @@ Definition tail031 (i:int31) :=
end)
i On.
-Register head031 as int31.head0.
-Register tail031 as int31.tail0.
+Numeral Notation int31 phi_inv_nonneg phi : int31_scope.
diff --git a/theories/Numbers/Cyclic/Int31/Ring31.v b/theories/Numbers/Cyclic/Int31/Ring31.v
index b693529451..eb47141cab 100644
--- a/theories/Numbers/Cyclic/Int31/Ring31.v
+++ b/theories/Numbers/Cyclic/Int31/Ring31.v
@@ -8,6 +8,8 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+(** This library has been deprecated since Coq version 8.10. *)
+
(** * Int31 numbers defines Z/(2^31)Z, and can hence be equipped
with a ring structure and a ring tactic *)
@@ -101,4 +103,3 @@ Let test : forall x y, 1 + x*y + x*x + 1 = 1*1 + 1 + y*x + 1*x*x.
intros. ring.
Qed.
End TestRing.
-
diff --git a/theories/Numbers/Cyclic/Int63/Cyclic63.v b/theories/Numbers/Cyclic/Int63/Cyclic63.v
new file mode 100644
index 0000000000..3b431d5b47
--- /dev/null
+++ b/theories/Numbers/Cyclic/Int63/Cyclic63.v
@@ -0,0 +1,330 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2018 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(** * Int63 numbers defines indeed a cyclic structure : Z/(2^31)Z *)
+
+(**
+Author: Arnaud Spiwack (+ Pierre Letouzey)
+*)
+Require Import CyclicAxioms.
+Require Export ZArith.
+Require Export Int63.
+Import Zpow_facts.
+Import Utf8.
+Import Lia.
+
+Local Open Scope int63_scope.
+(** {2 Operators } **)
+
+Definition Pdigits := Eval compute in P_of_succ_nat (size - 1).
+
+Fixpoint positive_to_int_rec (n:nat) (p:positive) :=
+ match n, p with
+ | O, _ => (Npos p, 0)
+ | S n, xH => (0%N, 1)
+ | S n, xO p =>
+ let (N,i) := positive_to_int_rec n p in
+ (N, i << 1)
+ | S n, xI p =>
+ let (N,i) := positive_to_int_rec n p in
+ (N, (i << 1) + 1)
+ end.
+
+Definition positive_to_int := positive_to_int_rec size.
+
+Definition mulc_WW x y :=
+ let (h, l) := mulc x y in
+ if is_zero h then
+ if is_zero l then W0
+ else WW h l
+ else WW h l.
+Notation "n '*c' m" := (mulc_WW n m) (at level 40, no associativity) : int63_scope.
+
+Definition pos_mod p x :=
+ if p <= digits then
+ let p := digits - p in
+ (x << p) >> p
+ else x.
+
+Notation pos_mod_int := pos_mod.
+
+Import ZnZ.
+
+Instance int_ops : ZnZ.Ops int :=
+{|
+ digits := Pdigits; (* number of digits *)
+ zdigits := Int63.digits; (* number of digits *)
+ to_Z := Int63.to_Z; (* conversion to Z *)
+ of_pos := positive_to_int; (* positive -> N*int63 : p => N,i
+ where p = N*2^31+phi i *)
+ head0 := Int63.head0; (* number of head 0 *)
+ tail0 := Int63.tail0; (* number of tail 0 *)
+ zero := 0;
+ one := 1;
+ minus_one := Int63.max_int;
+ compare := Int63.compare;
+ eq0 := Int63.is_zero;
+ opp_c := Int63.oppc;
+ opp := Int63.opp;
+ opp_carry := Int63.oppcarry;
+ succ_c := Int63.succc;
+ add_c := Int63.addc;
+ add_carry_c := Int63.addcarryc;
+ succ := Int63.succ;
+ add := Int63.add;
+ add_carry := Int63.addcarry;
+ pred_c := Int63.predc;
+ sub_c := Int63.subc;
+ sub_carry_c := Int63.subcarryc;
+ pred := Int63.pred;
+ sub := Int63.sub;
+ sub_carry := Int63.subcarry;
+ mul_c := mulc_WW;
+ mul := Int63.mul;
+ square_c := fun x => mulc_WW x x;
+ div21 := diveucl_21;
+ div_gt := diveucl; (* this is supposed to be the special case of
+ division a/b where a > b *)
+ div := diveucl;
+ modulo_gt := Int63.mod;
+ modulo := Int63.mod;
+ gcd_gt := Int63.gcd;
+ gcd := Int63.gcd;
+ add_mul_div := Int63.addmuldiv;
+ pos_mod := pos_mod_int;
+ is_even := Int63.is_even;
+ sqrt2 := Int63.sqrt2;
+ sqrt := Int63.sqrt;
+ ZnZ.lor := Int63.lor;
+ ZnZ.land := Int63.land;
+ ZnZ.lxor := Int63.lxor
+|}.
+
+Local Open Scope Z_scope.
+
+Lemma is_zero_spec_aux : forall x : int, is_zero x = true -> [|x|] = 0%Z.
+Proof.
+ intros x;rewrite is_zero_spec;intros H;rewrite H;trivial.
+Qed.
+
+Lemma positive_to_int_spec :
+ forall p : positive,
+ Zpos p =
+ Z_of_N (fst (positive_to_int p)) * wB + to_Z (snd (positive_to_int p)).
+Proof.
+ assert (H: (wB <= wB) -> forall p : positive,
+ Zpos p = Z_of_N (fst (positive_to_int p)) * wB + [|snd (positive_to_int p)|] /\
+ [|snd (positive_to_int p)|] < wB).
+ 2: intros p; case (H (Z.le_refl wB) p); auto.
+ unfold positive_to_int, wB at 1 3 4.
+ elim size.
+ intros _ p; simpl;
+ rewrite to_Z_0, Pmult_1_r; split; auto with zarith; apply refl_equal.
+ intros n; rewrite inj_S; unfold Z.succ; rewrite Zpower_exp, Z.pow_1_r; auto with zarith.
+ intros IH Hle p.
+ assert (F1: 2 ^ Z_of_nat n <= wB); auto with zarith.
+ assert (0 <= 2 ^ Z_of_nat n); auto with zarith.
+ case p; simpl.
+ intros p1.
+ generalize (IH F1 p1); case positive_to_int_rec; simpl.
+ intros n1 i (H1,H2).
+ rewrite Zpos_xI, H1.
+ replace [|i << 1 + 1|] with ([|i|] * 2 + 1).
+ split; auto with zarith; ring.
+ rewrite add_spec, lsl_spec, Zplus_mod_idemp_l, to_Z_1, Z.pow_1_r, Zmod_small; auto.
+ case (to_Z_bounded i); split; auto with zarith.
+ intros p1.
+ generalize (IH F1 p1); case positive_to_int_rec; simpl.
+ intros n1 i (H1,H2).
+ rewrite Zpos_xO, H1.
+ replace [|i << 1|] with ([|i|] * 2).
+ split; auto with zarith; ring.
+ rewrite lsl_spec, to_Z_1, Z.pow_1_r, Zmod_small; auto.
+ case (to_Z_bounded i); split; auto with zarith.
+ rewrite to_Z_1; assert (0 < 2^ Z_of_nat n); auto with zarith.
+Qed.
+
+Lemma mulc_WW_spec :
+ forall x y,[|| x *c y ||] = [|x|] * [|y|].
+Proof.
+ intros x y;unfold mulc_WW.
+ generalize (mulc_spec x y);destruct (mulc x y);simpl;intros Heq;rewrite Heq.
+ case_eq (is_zero i);intros;trivial.
+ apply is_zero_spec in H;rewrite H, to_Z_0.
+ case_eq (is_zero i0);intros;trivial.
+ apply is_zero_spec in H0;rewrite H0, to_Z_0, Zmult_comm;trivial.
+Qed.
+
+Lemma squarec_spec :
+ forall x,
+ [||x *c x||] = [|x|] * [|x|].
+Proof (fun x => mulc_WW_spec x x).
+
+Lemma diveucl_spec_aux : forall a b, 0 < [|b|] ->
+ let (q,r) := diveucl a b in
+ [|a|] = [|q|] * [|b|] + [|r|] /\
+ 0 <= [|r|] < [|b|].
+Proof.
+ intros a b H;assert (W:= diveucl_spec a b).
+ assert ([|b|]>0) by (auto with zarith).
+ generalize (Z_div_mod [|a|] [|b|] H0).
+ destruct (diveucl a b);destruct (Z.div_eucl [|a|] [|b|]).
+ inversion W;rewrite Zmult_comm;trivial.
+Qed.
+
+Lemma diveucl_21_spec_aux : forall a1 a2 b,
+ wB/2 <= [|b|] ->
+ [|a1|] < [|b|] ->
+ let (q,r) := diveucl_21 a1 a2 b in
+ [|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\
+ 0 <= [|r|] < [|b|].
+Proof.
+ intros a1 a2 b H1 H2;assert (W:= diveucl_21_spec a1 a2 b).
+ assert (W1:= to_Z_bounded a1).
+ assert ([|b|]>0) by (auto with zarith).
+ generalize (Z_div_mod ([|a1|]*wB+[|a2|]) [|b|] H).
+ destruct (diveucl_21 a1 a2 b);destruct (Z.div_eucl ([|a1|]*wB+[|a2|]) [|b|]).
+ inversion W;rewrite (Zmult_comm [|b|]);trivial.
+Qed.
+
+Lemma shift_unshift_mod_2 : forall n p a, 0 <= p <= n ->
+ ((a * 2 ^ (n - p)) mod (2^n) / 2 ^ (n - p)) mod (2^n) =
+ a mod 2 ^ p.
+ Proof.
+ intros n p a H.
+ rewrite Zmod_small.
+ - rewrite Zmod_eq by auto with zarith.
+ unfold Zminus at 1.
+ rewrite Zdiv.Z_div_plus_full_l by auto with zarith.
+ replace (2 ^ n) with (2 ^ (n - p) * 2 ^ p) by (rewrite <- Zpower_exp; [ f_equal | | ]; lia).
+ rewrite <- Zdiv_Zdiv, Z_div_mult by auto with zarith.
+ rewrite (Zmult_comm (2^(n-p))), Zmult_assoc.
+ rewrite Zopp_mult_distr_l.
+ rewrite Z_div_mult by auto with zarith.
+ symmetry; apply Zmod_eq; auto with zarith.
+ - remember (a * 2 ^ (n - p)) as b.
+ destruct (Z_mod_lt b (2^n)); auto with zarith.
+ split.
+ apply Z_div_pos; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ apply Z.lt_le_trans with (2^n); auto with zarith.
+ generalize (pow2_pos (n - p)); nia.
+ Qed.
+
+Lemma div_le_0 : forall p x, 0 <= x -> 0 <= x / 2 ^ p.
+ Proof.
+ intros p x Hle;destruct (Z_le_gt_dec 0 p).
+ apply Zdiv_le_lower_bound;auto with zarith.
+ replace (2^p) with 0.
+ destruct x;compute;intro;discriminate.
+ destruct p;trivial;discriminate.
+ Qed.
+
+Lemma div_lt : forall p x y, 0 <= x < y -> x / 2^p < y.
+ Proof.
+ intros p x y H;destruct (Z_le_gt_dec 0 p).
+ apply Zdiv_lt_upper_bound;auto with zarith.
+ apply Z.lt_le_trans with y;auto with zarith.
+ rewrite <- (Zmult_1_r y);apply Zmult_le_compat;auto with zarith.
+ assert (0 < 2^p);auto with zarith.
+ replace (2^p) with 0.
+ destruct x;change (0<y);auto with zarith.
+ destruct p;trivial;discriminate.
+ Qed.
+
+Lemma P (A B C: Prop) :
+ A → (B → C) → (A → B) → C.
+Proof. tauto. Qed.
+
+Lemma shift_unshift_mod_3:
+ forall n p a : Z,
+ 0 <= p <= n ->
+ (a * 2 ^ (n - p)) mod 2 ^ n / 2 ^ (n - p) = a mod 2 ^ p.
+Proof.
+ intros;rewrite <- (shift_unshift_mod_2 n p a);[ | auto with zarith].
+ symmetry;apply Zmod_small.
+ generalize (a * 2 ^ (n - p));intros w.
+ generalize (2 ^ (n - p)) (pow2_pos (n - p)); intros x; apply P. lia. intros hx.
+ generalize (2 ^ n) (pow2_pos n); intros y; apply P. lia. intros hy.
+ elim_div. intros q r. apply P. lia.
+ elim_div. intros z t. refine (P _ _ _ _ _). lia.
+ intros [ ? [ ht | ] ]; [ | lia ]; subst w.
+ intros [ ? [ hr | ] ]; [ | lia ]; subst t.
+ nia.
+Qed.
+
+Lemma pos_mod_spec w p : φ(pos_mod p w) = φ(w) mod (2 ^ φ(p)).
+Proof.
+ simpl. unfold pos_mod_int.
+ assert (W:=to_Z_bounded p);assert (W':=to_Z_bounded Int63.digits);assert (W'' := to_Z_bounded w).
+ case lebP; intros hle.
+ 2: {
+ symmetry; apply Zmod_small.
+ assert (2 ^ [|Int63.digits|] < 2 ^ [|p|]); [ apply Zpower_lt_monotone; auto with zarith | ].
+ change wB with (2 ^ [|Int63.digits|]) in *; auto with zarith. }
+ rewrite <- (shift_unshift_mod_3 [|Int63.digits|] [|p|] [|w|]) by auto with zarith.
+ replace ([|Int63.digits|] - [|p|]) with [|Int63.digits - p|] by (rewrite sub_spec, Zmod_small; auto with zarith).
+ rewrite lsr_spec, lsl_spec; reflexivity.
+Qed.
+
+(** {2 Specification and proof} **)
+Global Instance int_specs : ZnZ.Specs int_ops := {
+ spec_to_Z := to_Z_bounded;
+ spec_of_pos := positive_to_int_spec;
+ spec_zdigits := refl_equal _;
+ spec_more_than_1_digit:= refl_equal _;
+ spec_0 := to_Z_0;
+ spec_1 := to_Z_1;
+ spec_m1 := refl_equal _;
+ spec_compare := compare_spec;
+ spec_eq0 := is_zero_spec_aux;
+ spec_opp_c := oppc_spec;
+ spec_opp := opp_spec;
+ spec_opp_carry := oppcarry_spec;
+ spec_succ_c := succc_spec;
+ spec_add_c := addc_spec;
+ spec_add_carry_c := addcarryc_spec;
+ spec_succ := succ_spec;
+ spec_add := add_spec;
+ spec_add_carry := addcarry_spec;
+ spec_pred_c := predc_spec;
+ spec_sub_c := subc_spec;
+ spec_sub_carry_c := subcarryc_spec;
+ spec_pred := pred_spec;
+ spec_sub := sub_spec;
+ spec_sub_carry := subcarry_spec;
+ spec_mul_c := mulc_WW_spec;
+ spec_mul := mul_spec;
+ spec_square_c := squarec_spec;
+ spec_div21 := diveucl_21_spec_aux;
+ spec_div_gt := fun a b _ => diveucl_spec_aux a b;
+ spec_div := diveucl_spec_aux;
+ spec_modulo_gt := fun a b _ _ => mod_spec a b;
+ spec_modulo := fun a b _ => mod_spec a b;
+ spec_gcd_gt := fun a b _ => gcd_spec a b;
+ spec_gcd := gcd_spec;
+ spec_head00 := head00_spec;
+ spec_head0 := head0_spec;
+ spec_tail00 := tail00_spec;
+ spec_tail0 := tail0_spec;
+ spec_add_mul_div := addmuldiv_spec;
+ spec_pos_mod := pos_mod_spec;
+ spec_is_even := is_even_spec;
+ spec_sqrt2 := sqrt2_spec;
+ spec_sqrt := sqrt_spec;
+ spec_land := land_spec';
+ spec_lor := lor_spec';
+ spec_lxor := lxor_spec' }.
+
+
+
+Module Int63Cyclic <: CyclicType.
+ Definition t := int.
+ Definition ops := int_ops.
+ Definition specs := int_specs.
+End Int63Cyclic.
diff --git a/theories/Numbers/Cyclic/Int63/Int63.v b/theories/Numbers/Cyclic/Int63/Int63.v
new file mode 100644
index 0000000000..eac26add03
--- /dev/null
+++ b/theories/Numbers/Cyclic/Int63/Int63.v
@@ -0,0 +1,1918 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+(* Benjamin Gregoire, Laurent Thery, INRIA, 2007 *)
+(************************************************************************)
+
+Require Import Utf8.
+Require Export DoubleType.
+Require Import Lia.
+Require Import Zpow_facts.
+Require Import Zgcd_alt.
+Import Znumtheory.
+
+Register bool as kernel.ind_bool.
+Register prod as kernel.ind_pair.
+Register carry as kernel.ind_carry.
+Register comparison as kernel.ind_cmp.
+
+Definition size := 63%nat.
+
+Primitive int := #int63_type.
+Register int as num.int63.type.
+Declare Scope int63_scope.
+Definition id_int : int -> int := fun x => x.
+Declare ML Module "int63_syntax_plugin".
+
+Delimit Scope int63_scope with int63.
+Bind Scope int63_scope with int.
+
+(* Logical operations *)
+Primitive lsl := #int63_lsl.
+Infix "<<" := lsl (at level 30, no associativity) : int63_scope.
+
+Primitive lsr := #int63_lsr.
+Infix ">>" := lsr (at level 30, no associativity) : int63_scope.
+
+Primitive land := #int63_land.
+Infix "land" := land (at level 40, left associativity) : int63_scope.
+
+Primitive lor := #int63_lor.
+Infix "lor" := lor (at level 40, left associativity) : int63_scope.
+
+Primitive lxor := #int63_lxor.
+Infix "lxor" := lxor (at level 40, left associativity) : int63_scope.
+
+(* Arithmetic modulo operations *)
+Primitive add := #int63_add.
+Notation "n + m" := (add n m) : int63_scope.
+
+Primitive sub := #int63_sub.
+Notation "n - m" := (sub n m) : int63_scope.
+
+Primitive mul := #int63_mul.
+Notation "n * m" := (mul n m) : int63_scope.
+
+Primitive mulc := #int63_mulc.
+
+Primitive div := #int63_div.
+Notation "n / m" := (div n m) : int63_scope.
+
+Primitive mod := #int63_mod.
+Notation "n '\%' m" := (mod n m) (at level 40, left associativity) : int63_scope.
+
+(* Comparisons *)
+Primitive eqb := #int63_eq.
+Notation "m '==' n" := (eqb m n) (at level 70, no associativity) : int63_scope.
+
+Primitive ltb := #int63_lt.
+Notation "m < n" := (ltb m n) : int63_scope.
+
+Primitive leb := #int63_le.
+Notation "m <= n" := (leb m n) : int63_scope.
+Notation "m ≤ n" := (leb m n) (at level 70, no associativity) : int63_scope.
+
+Local Open Scope int63_scope.
+
+(** The number of digits as a int *)
+Definition digits := 63.
+
+(** The bigger int *)
+Definition max_int := Eval vm_compute in 0 - 1.
+Register Inline max_int.
+
+(** Access to the nth digits *)
+Definition get_digit x p := (0 < (x land (1 << p))).
+
+Definition set_digit x p (b:bool) :=
+ if if 0 <= p then p < digits else false then
+ if b then x lor (1 << p)
+ else x land (max_int lxor (1 << p))
+ else x.
+
+(** Equality to 0 *)
+Definition is_zero (i:int) := i == 0.
+Register Inline is_zero.
+
+(** Parity *)
+Definition is_even (i:int) := is_zero (i land 1).
+Register Inline is_even.
+
+(** Bit *)
+
+Definition bit i n := negb (is_zero ((i >> n) << (digits - 1))).
+(* Register bit as PrimInline. *)
+
+(** Extra modulo operations *)
+Definition opp (i:int) := 0 - i.
+Register Inline opp.
+Notation "- x" := (opp x) : int63_scope.
+
+Definition oppcarry i := max_int - i.
+Register Inline oppcarry.
+
+Definition succ i := i + 1.
+Register Inline succ.
+
+Definition pred i := i - 1.
+Register Inline pred.
+
+Definition addcarry i j := i + j + 1.
+Register Inline addcarry.
+
+Definition subcarry i j := i - j - 1.
+Register Inline subcarry.
+
+(** Exact arithmetic operations *)
+
+Definition addc_def x y :=
+ let r := x + y in
+ if r < x then C1 r else C0 r.
+(* the same but direct implementation for effeciancy *)
+Primitive addc := #int63_addc.
+Notation "n '+c' m" := (addc n m) (at level 50, no associativity) : int63_scope.
+
+Definition addcarryc_def x y :=
+ let r := addcarry x y in
+ if r <= x then C1 r else C0 r.
+(* the same but direct implementation for effeciancy *)
+Primitive addcarryc := #int63_addcarryc.
+
+Definition subc_def x y :=
+ if y <= x then C0 (x - y) else C1 (x - y).
+(* the same but direct implementation for effeciancy *)
+Primitive subc := #int63_subc.
+Notation "n '-c' m" := (subc n m) (at level 50, no associativity) : int63_scope.
+
+Definition subcarryc_def x y :=
+ if y < x then C0 (x - y - 1) else C1 (x - y - 1).
+(* the same but direct implementation for effeciancy *)
+Primitive subcarryc := #int63_subcarryc.
+
+Definition diveucl_def x y := (x/y, x\%y).
+(* the same but direct implementation for effeciancy *)
+Primitive diveucl := #int63_diveucl.
+
+Primitive diveucl_21 := #int63_div21.
+
+Definition addmuldiv_def p x y :=
+ (x << p) lor (y >> (digits - p)).
+Primitive addmuldiv := #int63_addmuldiv.
+
+Definition oppc (i:int) := 0 -c i.
+Register Inline oppc.
+
+Definition succc i := i +c 1.
+Register Inline succc.
+
+Definition predc i := i -c 1.
+Register Inline predc.
+
+(** Comparison *)
+Definition compare_def x y :=
+ if x < y then Lt
+ else if (x == y) then Eq else Gt.
+
+Primitive compare := #int63_compare.
+Notation "n ?= m" := (compare n m) (at level 70, no associativity) : int63_scope.
+
+Import Bool ZArith.
+(** Translation to Z *)
+Fixpoint to_Z_rec (n:nat) (i:int) :=
+ match n with
+ | O => 0%Z
+ | S n =>
+ (if is_even i then Z.double else Zdouble_plus_one) (to_Z_rec n (i >> 1))
+ end.
+
+Definition to_Z := to_Z_rec size.
+
+Fixpoint of_pos_rec (n:nat) (p:positive) :=
+ match n, p with
+ | O, _ => 0
+ | S n, xH => 1
+ | S n, xO p => (of_pos_rec n p) << 1
+ | S n, xI p => (of_pos_rec n p) << 1 lor 1
+ end.
+
+Definition of_pos := of_pos_rec size.
+
+Definition of_Z z :=
+ match z with
+ | Zpos p => of_pos p
+ | Z0 => 0
+ | Zneg p => - (of_pos p)
+ end.
+
+Notation "[| x |]" := (to_Z x) (at level 0, x at level 99) : int63_scope.
+
+Definition wB := (2 ^ (Z.of_nat size))%Z.
+
+Lemma to_Z_rec_bounded size : forall x, (0 <= to_Z_rec size x < 2 ^ Z.of_nat size)%Z.
+Proof.
+ elim size. simpl; auto with zarith.
+ intros n ih x; rewrite inj_S; simpl; assert (W := ih (x >> 1)%int63).
+ rewrite Z.pow_succ_r; auto with zarith.
+ destruct (is_even x).
+ rewrite Zdouble_mult; auto with zarith.
+ rewrite Zdouble_plus_one_mult; auto with zarith.
+Qed.
+
+Corollary to_Z_bounded : forall x, (0 <= [| x |] < wB)%Z.
+Proof. apply to_Z_rec_bounded. Qed.
+
+(* =================================================== *)
+Local Open Scope Z_scope.
+(* General arithmetic results *)
+Lemma Z_lt_div2 x y : x < 2 * y -> x / 2 < y.
+Proof. apply Z.div_lt_upper_bound; reflexivity. Qed.
+
+Theorem Zmod_le_first a b : 0 <= a -> 0 < b -> 0 <= a mod b <= a.
+Proof.
+ intros ha hb; case (Z_mod_lt a b); [ auto with zarith | ]; intros p q; apply (conj p).
+ case (Z.le_gt_cases b a). lia.
+ intros hlt; rewrite Zmod_small; lia.
+Qed.
+
+Theorem Zmod_distr: forall a b r t, 0 <= a <= b -> 0 <= r -> 0 <= t < 2 ^a ->
+ (2 ^a * r + t) mod (2 ^ b) = (2 ^a * r) mod (2 ^ b) + t.
+Proof.
+ intros a b r t (H1, H2) H3 (H4, H5).
+ assert (t < 2 ^ b).
+ apply Z.lt_le_trans with (1:= H5); auto with zarith.
+ apply Zpower_le_monotone; auto with zarith.
+ rewrite Zplus_mod; auto with zarith.
+ rewrite -> Zmod_small with (a := t); auto with zarith.
+ apply Zmod_small; auto with zarith.
+ split; auto with zarith.
+ assert (0 <= 2 ^a * r); auto with zarith.
+ apply Z.add_nonneg_nonneg; auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end;
+ auto with zarith.
+ pattern (2 ^ b) at 2; replace (2 ^ b) with ((2 ^ b - 2 ^a) + 2 ^ a);
+ try ring.
+ apply Z.add_le_lt_mono; auto with zarith.
+ replace b with ((b - a) + a); try ring.
+ rewrite Zpower_exp; auto with zarith.
+ pattern (2 ^a) at 4; rewrite <- (Z.mul_1_l (2 ^a));
+ try rewrite <- Z.mul_sub_distr_r.
+ rewrite (Z.mul_comm (2 ^(b - a))); rewrite Zmult_mod_distr_l;
+ auto with zarith.
+ rewrite (Z.mul_comm (2 ^a)); apply Z.mul_le_mono_nonneg_r; auto with zarith.
+ match goal with |- context [?X mod ?Y] => case (Z_mod_lt X Y) end.
+ apply Z.lt_gt; auto with zarith.
+ auto with zarith.
+Qed.
+
+(* Results about pow2 *)
+Lemma pow2_pos n : 0 <= n → 2 ^ n > 0.
+Proof. intros h; apply Z.lt_gt, Zpower_gt_0; lia. Qed.
+
+Lemma pow2_nz n : 0 <= n → 2 ^ n ≠ 0.
+Proof. intros h; generalize (pow2_pos _ h); lia. Qed.
+
+Hint Resolve pow2_pos pow2_nz : zarith.
+
+(* =================================================== *)
+
+(** Trivial lemmas without axiom *)
+
+Lemma wB_diff_0 : wB <> 0.
+Proof. exact (fun x => let 'eq_refl := x in idProp). Qed.
+
+Lemma wB_pos : 0 < wB.
+Proof. reflexivity. Qed.
+
+Lemma to_Z_0 : [|0|] = 0.
+Proof. reflexivity. Qed.
+
+Lemma to_Z_1 : [|1|] = 1.
+Proof. reflexivity. Qed.
+
+(* Notations *)
+Local Open Scope Z_scope.
+
+Notation "[+| c |]" :=
+ (interp_carry 1 wB to_Z c) (at level 0, c at level 99) : int63_scope.
+
+Notation "[-| c |]" :=
+ (interp_carry (-1) wB to_Z c) (at level 0, c at level 99) : int63_scope.
+
+Notation "[|| x ||]" :=
+ (zn2z_to_Z wB to_Z x) (at level 0, x at level 99) : int63_scope.
+
+(* Bijection : int63 <-> Bvector size *)
+
+Axiom of_to_Z : forall x, of_Z [| x |] = x.
+
+Notation "'φ' x" := [| x |] (at level 0) : int63_scope.
+
+Lemma can_inj {rT aT} {f: aT -> rT} {g: rT -> aT} (K: forall a, g (f a) = a) {a a'} (e: f a = f a') : a = a'.
+Proof. generalize (K a) (K a'). congruence. Qed.
+
+Lemma to_Z_inj x y : φ x = φ y → x = y.
+Proof. exact (λ e, can_inj of_to_Z e). Qed.
+
+(** Specification of logical operations *)
+Local Open Scope Z_scope.
+Axiom lsl_spec : forall x p, [| x << p |] = [| x |] * 2 ^ [| p |] mod wB.
+
+Axiom lsr_spec : forall x p, [|x >> p|] = [|x|] / 2 ^ [|p|].
+
+Axiom land_spec: forall x y i , bit (x land y) i = bit x i && bit y i.
+
+Axiom lor_spec: forall x y i, bit (x lor y) i = bit x i || bit y i.
+
+Axiom lxor_spec: forall x y i, bit (x lxor y) i = xorb (bit x i) (bit y i).
+
+(** Specification of basic opetations *)
+
+(* Arithmetic modulo operations *)
+
+(* Remarque : les axiomes seraient plus simple si on utilise of_Z a la place :
+ exemple : add_spec : forall x y, of_Z (x + y) = of_Z x + of_Z y. *)
+
+Axiom add_spec : forall x y, [|x + y|] = ([|x|] + [|y|]) mod wB.
+
+Axiom sub_spec : forall x y, [|x - y|] = ([|x|] - [|y|]) mod wB.
+
+Axiom mul_spec : forall x y, [| x * y |] = [|x|] * [|y|] mod wB.
+
+Axiom mulc_spec : forall x y, [|x|] * [|y|] = [|fst (mulc x y)|] * wB + [|snd (mulc x y)|].
+
+Axiom div_spec : forall x y, [|x / y|] = [|x|] / [|y|].
+
+Axiom mod_spec : forall x y, [|x \% y|] = [|x|] mod [|y|].
+
+(* Comparisons *)
+Axiom eqb_correct : forall i j, (i == j)%int63 = true -> i = j.
+
+Axiom eqb_refl : forall x, (x == x)%int63 = true.
+
+Axiom ltb_spec : forall x y, (x < y)%int63 = true <-> [|x|] < [|y|].
+
+Axiom leb_spec : forall x y, (x <= y)%int63 = true <-> [|x|] <= [|y|].
+
+(** Exotic operations *)
+
+(** I should add the definition (like for compare) *)
+Primitive head0 := #int63_head0.
+Primitive tail0 := #int63_tail0.
+
+(** Axioms on operations which are just short cut *)
+
+Axiom compare_def_spec : forall x y, compare x y = compare_def x y.
+
+Axiom head0_spec : forall x, 0 < [|x|] ->
+ wB/ 2 <= 2 ^ ([|head0 x|]) * [|x|] < wB.
+
+Axiom tail0_spec : forall x, 0 < [|x|] ->
+ (exists y, 0 <= y /\ [|x|] = (2 * y + 1) * (2 ^ [|tail0 x|]))%Z.
+
+Axiom addc_def_spec : forall x y, (x +c y)%int63 = addc_def x y.
+
+Axiom addcarryc_def_spec : forall x y, addcarryc x y = addcarryc_def x y.
+
+Axiom subc_def_spec : forall x y, (x -c y)%int63 = subc_def x y.
+
+Axiom subcarryc_def_spec : forall x y, subcarryc x y = subcarryc_def x y.
+
+Axiom diveucl_def_spec : forall x y, diveucl x y = diveucl_def x y.
+
+Axiom diveucl_21_spec : forall a1 a2 b,
+ let (q,r) := diveucl_21 a1 a2 b in
+ ([|q|],[|r|]) = Z.div_eucl ([|a1|] * wB + [|a2|]) [|b|].
+
+Axiom addmuldiv_def_spec : forall p x y,
+ addmuldiv p x y = addmuldiv_def p x y.
+
+(** Square root functions using newton iteration **)
+Local Open Scope int63_scope.
+
+Definition sqrt_step (rec: int -> int -> int) (i j: int) :=
+ let quo := i / j in
+ if quo < j then rec i ((j + quo) >> 1)
+ else j.
+
+Definition iter_sqrt :=
+ Eval lazy beta delta [sqrt_step] in
+ fix iter_sqrt (n: nat) (rec: int -> int -> int)
+ (i j: int) {struct n} : int :=
+ sqrt_step
+ (fun i j => match n with
+ O => rec i j
+ | S n => (iter_sqrt n (iter_sqrt n rec)) i j
+ end) i j.
+
+Definition sqrt i :=
+ match compare 1 i with
+ Gt => 0
+ | Eq => 1
+ | Lt => iter_sqrt size (fun i j => j) i (i >> 1)
+ end.
+
+Definition high_bit := 1 << (digits - 1).
+
+Definition sqrt2_step (rec: int -> int -> int -> int)
+ (ih il j: int) :=
+ if ih < j then
+ let (quo,_) := diveucl_21 ih il j in
+ if quo < j then
+ match j +c quo with
+ | C0 m1 => rec ih il (m1 >> 1)
+ | C1 m1 => rec ih il ((m1 >> 1) + high_bit)
+ end
+ else j
+ else j.
+
+Definition iter2_sqrt :=
+ Eval lazy beta delta [sqrt2_step] in
+ fix iter2_sqrt (n: nat)
+ (rec: int -> int -> int -> int)
+ (ih il j: int) {struct n} : int :=
+ sqrt2_step
+ (fun ih il j =>
+ match n with
+ | O => rec ih il j
+ | S n => (iter2_sqrt n (iter2_sqrt n rec)) ih il j
+ end) ih il j.
+
+Definition sqrt2 ih il :=
+ let s := iter2_sqrt size (fun ih il j => j) ih il max_int in
+ let (ih1, il1) := mulc s s in
+ match il -c il1 with
+ | C0 il2 =>
+ if ih1 < ih then (s, C1 il2) else (s, C0 il2)
+ | C1 il2 =>
+ if ih1 < (ih - 1) then (s, C1 il2) else (s, C0 il2)
+ end.
+
+(** Gcd **)
+Fixpoint gcd_rec (guard:nat) (i j:int) {struct guard} :=
+ match guard with
+ | O => 1
+ | S p => if j == 0 then i else gcd_rec p j (i \% j)
+ end.
+
+Definition gcd := gcd_rec (2*size).
+
+(** equality *)
+Lemma eqb_complete : forall x y, x = y -> (x == y) = true.
+Proof.
+ intros x y H; rewrite -> H, eqb_refl;trivial.
+Qed.
+
+Lemma eqb_spec : forall x y, (x == y) = true <-> x = y.
+Proof.
+ split;auto using eqb_correct, eqb_complete.
+Qed.
+
+Lemma eqb_false_spec : forall x y, (x == y) = false <-> x <> y.
+Proof.
+ intros;rewrite <- not_true_iff_false, eqb_spec;split;trivial.
+Qed.
+
+Lemma eqb_false_complete : forall x y, x <> y -> (x == y) = false.
+Proof.
+ intros x y;rewrite eqb_false_spec;trivial.
+Qed.
+
+Lemma eqb_false_correct : forall x y, (x == y) = false -> x <> y.
+Proof.
+ intros x y;rewrite eqb_false_spec;trivial.
+Qed.
+
+Definition eqs (i j : int) : {i = j} + { i <> j } :=
+ (if i == j as b return ((b = true -> i = j) -> (b = false -> i <> j) -> {i=j} + {i <> j} )
+ then fun (Heq : true = true -> i = j) _ => left _ (Heq (eq_refl true))
+ else fun _ (Hdiff : false = false -> i <> j) => right _ (Hdiff (eq_refl false)))
+ (eqb_correct i j)
+ (eqb_false_correct i j).
+
+Lemma eq_dec : forall i j:int, i = j \/ i <> j.
+Proof.
+ intros i j;destruct (eqs i j);auto.
+Qed.
+
+(* Extra function on equality *)
+
+Definition cast i j :=
+ (if i == j as b return ((b = true -> i = j) -> option (forall P : int -> Type, P i -> P j))
+ then fun Heq : true = true -> i = j =>
+ Some
+ (fun (P : int -> Type) (Hi : P i) =>
+ match Heq (eq_refl true) in (_ = y) return (P y) with
+ | eq_refl => Hi
+ end)
+ else fun _ : false = true -> i = j => None) (eqb_correct i j).
+
+Lemma cast_refl : forall i, cast i i = Some (fun P H => H).
+Proof.
+ unfold cast;intros.
+ generalize (eqb_correct i i).
+ rewrite eqb_refl;intros.
+ rewrite (Eqdep_dec.eq_proofs_unicity eq_dec (e (eq_refl true)) (eq_refl i));trivial.
+Qed.
+
+Lemma cast_diff : forall i j, i == j = false -> cast i j = None.
+Proof.
+ intros;unfold cast;intros; generalize (eqb_correct i j).
+ rewrite H;trivial.
+Qed.
+
+Definition eqo i j :=
+ (if i == j as b return ((b = true -> i = j) -> option (i=j))
+ then fun Heq : true = true -> i = j =>
+ Some (Heq (eq_refl true))
+ else fun _ : false = true -> i = j => None) (eqb_correct i j).
+
+Lemma eqo_refl : forall i, eqo i i = Some (eq_refl i).
+Proof.
+ unfold eqo;intros.
+ generalize (eqb_correct i i).
+ rewrite eqb_refl;intros.
+ rewrite (Eqdep_dec.eq_proofs_unicity eq_dec (e (eq_refl true)) (eq_refl i));trivial.
+Qed.
+
+Lemma eqo_diff : forall i j, i == j = false -> eqo i j = None.
+Proof.
+ unfold eqo;intros; generalize (eqb_correct i j).
+ rewrite H;trivial.
+Qed.
+
+(** Comparison *)
+
+Lemma eqbP x y : reflect ([| x |] = [| y |]) (x == y).
+Proof. apply iff_reflect; rewrite eqb_spec; split; [ apply to_Z_inj | apply f_equal ]. Qed.
+
+Lemma ltbP x y : reflect ([| x |] < [| y |])%Z (x < y).
+Proof. apply iff_reflect; symmetry; apply ltb_spec. Qed.
+
+Lemma lebP x y : reflect ([| x |] <= [| y |])%Z (x ≤ y).
+Proof. apply iff_reflect; symmetry; apply leb_spec. Qed.
+
+Lemma compare_spec x y : compare x y = ([|x|] ?= [|y|])%Z.
+Proof.
+ rewrite compare_def_spec; unfold compare_def.
+ case ltbP; [ auto using Z.compare_lt_iff | intros hge ].
+ case eqbP; [ now symmetry; apply Z.compare_eq_iff | intros hne ].
+ symmetry; apply Z.compare_gt_iff; lia.
+Qed.
+
+Lemma is_zero_spec x : is_zero x = true <-> x = 0%int63.
+Proof. apply eqb_spec. Qed.
+
+Lemma diveucl_spec x y :
+ let (q,r) := diveucl x y in
+ ([| q |], [| r |]) = Z.div_eucl [| x |] [| y |].
+Proof.
+ rewrite diveucl_def_spec; unfold diveucl_def; rewrite div_spec, mod_spec; unfold Z.div, Zmod.
+ destruct (Z.div_eucl [| x |] [| y |]); trivial.
+Qed.
+
+Local Open Scope Z_scope.
+(** Addition *)
+Lemma addc_spec x y : [+| x +c y |] = [| x |] + [| y |].
+Proof.
+ rewrite addc_def_spec; unfold addc_def, interp_carry.
+ pose proof (to_Z_bounded x); pose proof (to_Z_bounded y).
+ case ltbP; rewrite add_spec.
+ case (Z_lt_ge_dec ([| x |] + [| y |]) wB).
+ intros k; rewrite Zmod_small; lia.
+ intros hge; rewrite <- (Zmod_unique _ _ 1 ([| x |] + [| y |] - wB)); lia.
+ case (Z_lt_ge_dec ([| x |] + [| y |]) wB).
+ intros k; rewrite Zmod_small; lia.
+ intros hge; rewrite <- (Zmod_unique _ _ 1 ([| x |] + [| y |] - wB)); lia.
+Qed.
+
+Lemma succ_spec x : [| succ x |] = ([| x |] + 1) mod wB.
+Proof. apply add_spec. Qed.
+
+Lemma succc_spec x : [+| succc x |] = [| x |] + 1.
+Proof. apply addc_spec. Qed.
+
+Lemma addcarry_spec x y : [| addcarry x y |] = ([| x |] + [| y |] + 1) mod wB.
+Proof. unfold addcarry; rewrite -> !add_spec, Zplus_mod_idemp_l; trivial. Qed.
+
+Lemma addcarryc_spec x y : [+| addcarryc x y |] = [| x |] + [| y |] + 1.
+Proof.
+ rewrite addcarryc_def_spec; unfold addcarryc_def, interp_carry.
+ pose proof (to_Z_bounded x); pose proof (to_Z_bounded y).
+ case lebP; rewrite addcarry_spec.
+ case (Z_lt_ge_dec ([| x |] + [| y |] + 1) wB).
+ intros hlt; rewrite Zmod_small; lia.
+ intros hge; rewrite <- (Zmod_unique _ _ 1 ([| x |] + [| y |] + 1 - wB)); lia.
+ case (Z_lt_ge_dec ([| x |] + [| y |] + 1) wB).
+ intros hlt; rewrite Zmod_small; lia.
+ intros hge; rewrite <- (Zmod_unique _ _ 1 ([| x |] + [| y |] + 1 - wB)); lia.
+Qed.
+
+(** Subtraction *)
+Lemma subc_spec x y : [-| x -c y |] = [| x |] - [| y |].
+Proof.
+ rewrite subc_def_spec; unfold subc_def; unfold interp_carry.
+ pose proof (to_Z_bounded x); pose proof (to_Z_bounded y).
+ case lebP.
+ intros hle; rewrite sub_spec, Z.mod_small; lia.
+ intros hgt; rewrite sub_spec, <- (Zmod_unique _ wB (-1) ([| x |] - [| y |] + wB)); lia.
+Qed.
+
+Lemma pred_spec x : [| pred x |] = ([| x |] - 1) mod wB.
+Proof. apply sub_spec. Qed.
+
+Lemma predc_spec x : [-| predc x |] = [| x |] - 1.
+Proof. apply subc_spec. Qed.
+
+Lemma oppc_spec x : [-| oppc x |] = - [| x |].
+Proof. unfold oppc; rewrite -> subc_spec, to_Z_0; trivial. Qed.
+
+Lemma opp_spec x : [|- x |] = - [| x |] mod wB.
+Proof. unfold opp; rewrite -> sub_spec, to_Z_0; trivial. Qed.
+
+Lemma oppcarry_spec x : [| oppcarry x |] = wB - [| x |] - 1.
+Proof.
+ unfold oppcarry; rewrite sub_spec.
+ rewrite <- Zminus_plus_distr, Zplus_comm, Zminus_plus_distr.
+ apply Zmod_small.
+ generalize (to_Z_bounded x); auto with zarith.
+Qed.
+
+Lemma subcarry_spec x y : [| subcarry x y |] = ([| x |] - [| y |] - 1) mod wB.
+Proof. unfold subcarry; rewrite !sub_spec, Zminus_mod_idemp_l; trivial. Qed.
+
+Lemma subcarryc_spec x y : [-| subcarryc x y |] = [| x |] - [| y |] - 1.
+Proof.
+ rewrite subcarryc_def_spec; unfold subcarryc_def, interp_carry; fold (subcarry x y).
+ pose proof (to_Z_bounded x); pose proof (to_Z_bounded y).
+ case ltbP; rewrite subcarry_spec.
+ intros hlt; rewrite Zmod_small; lia.
+ intros hge; rewrite <- (Zmod_unique _ _ (-1) ([| x |] - [| y |] - 1 + wB)); lia.
+Qed.
+
+(** GCD *)
+Lemma to_Z_gcd : forall i j, [| gcd i j |] = Zgcdn (2 * size) [| j |] [| i |].
+Proof.
+ unfold gcd.
+ elim (2*size)%nat. reflexivity.
+ intros n ih i j; simpl.
+ pose proof (to_Z_bounded j) as hj; pose proof (to_Z_bounded i).
+ case eqbP; rewrite to_Z_0.
+ intros ->; rewrite Z.abs_eq; lia.
+ intros hne; rewrite ih; clear ih.
+ rewrite <- mod_spec.
+ revert hj hne; case [| j |]; intros; lia.
+Qed.
+
+Lemma gcd_spec a b : Zis_gcd [| a |] [| b |] [| gcd a b |].
+Proof.
+ rewrite to_Z_gcd.
+ apply Zis_gcd_sym.
+ apply Zgcdn_is_gcd.
+ unfold Zgcd_bound.
+ generalize (to_Z_bounded b).
+ destruct [|b|].
+ unfold size; auto with zarith.
+ intros (_,H).
+ cut (Psize p <= size)%nat; [ lia | rewrite <- Zpower2_Psize; auto].
+ intros (H,_); compute in H; elim H; auto.
+Qed.
+
+(** Head0, Tail0 *)
+Lemma head00_spec x : [| x |] = 0 -> [| head0 x |] = [| digits |].
+Proof. now intros h; rewrite (to_Z_inj _ 0 h). Qed.
+
+Lemma tail00_spec x : [| x |] = 0 -> [|tail0 x|] = [|digits|].
+Proof. now intros h; rewrite (to_Z_inj _ 0 h). Qed.
+
+Infix "≡" := (eqm wB) (at level 80) : int63_scope.
+
+Lemma eqm_mod x y : x mod wB ≡ y mod wB → x ≡ y.
+Proof.
+ intros h.
+ eapply (eqm_trans).
+ apply eqm_sym; apply Zmod_eqm.
+ apply (eqm_trans _ _ _ _ h).
+ apply Zmod_eqm.
+Qed.
+
+Lemma eqm_sub x y : x ≡ y → x - y ≡ 0.
+Proof. intros h; unfold eqm; rewrite Zminus_mod, h, Z.sub_diag; reflexivity. Qed.
+
+Lemma eqmE x y : x ≡ y → ∃ k, x - y = k * wB.
+Proof.
+ intros h.
+ exact (Zmod_divide (x - y) wB (λ e, let 'eq_refl := e in I) (eqm_sub _ _ h)).
+Qed.
+
+Lemma eqm_subE x y : x ≡ y ↔ x - y ≡ 0.
+Proof.
+ split. apply eqm_sub.
+ intros h; case (eqmE _ _ h); clear h; intros q h.
+ assert (y = x - q * wB) by lia.
+ clear h; subst y.
+ unfold eqm; rewrite Zminus_mod, Z_mod_mult, Z.sub_0_r, Zmod_mod; reflexivity.
+Qed.
+
+Lemma int_eqm x y : x = y → φ x ≡ φ y.
+Proof. unfold eqm; intros ->; reflexivity. Qed.
+
+Lemma eqmI x y : φ x ≡ φ y → x = y.
+Proof.
+ unfold eqm.
+ repeat rewrite Zmod_small by apply to_Z_bounded.
+ apply to_Z_inj.
+Qed.
+
+(* ADD *)
+Lemma add_assoc x y z: (x + (y + z) = (x + y) + z)%int63.
+Proof.
+ apply to_Z_inj; rewrite !add_spec.
+ rewrite -> Zplus_mod_idemp_l, Zplus_mod_idemp_r, Zplus_assoc; auto.
+Qed.
+
+Lemma add_comm x y: (x + y = y + x)%int63.
+Proof.
+ apply to_Z_inj; rewrite -> !add_spec, Zplus_comm; auto.
+Qed.
+
+Lemma add_le_r m n:
+ if (n <= m + n)%int63 then ([|m|] + [|n|] < wB)%Z else (wB <= [|m|] + [|n|])%Z.
+Proof.
+ case (to_Z_bounded m); intros H1m H2m.
+ case (to_Z_bounded n); intros H1n H2n.
+ case (Zle_or_lt wB ([|m|] + [|n|])); intros H.
+ assert (H1: ([| m + n |] = [|m|] + [|n|] - wB)%Z).
+ rewrite add_spec.
+ replace (([|m|] + [|n|]) mod wB)%Z with (((([|m|] + [|n|]) - wB) + wB) mod wB)%Z.
+ rewrite -> Zplus_mod, Z_mod_same_full, Zplus_0_r, !Zmod_small; auto with zarith.
+ rewrite !Zmod_small; auto with zarith.
+ apply f_equal2 with (f := Zmod); auto with zarith.
+ case_eq (n <= m + n)%int63; auto.
+ rewrite leb_spec, H1; auto with zarith.
+ assert (H1: ([| m + n |] = [|m|] + [|n|])%Z).
+ rewrite add_spec, Zmod_small; auto with zarith.
+ replace (n <= m + n)%int63 with true; auto.
+ apply sym_equal; rewrite leb_spec, H1; auto with zarith.
+Qed.
+
+Lemma add_cancel_l x y z : (x + y = x + z)%int63 -> y = z.
+Proof.
+ intros h; apply int_eqm in h; rewrite !add_spec in h; apply eqm_mod, eqm_sub in h.
+ replace (_ + _ - _) with (φ(y) - φ(z)) in h by lia.
+ rewrite <- eqm_subE in h.
+ apply eqmI, h.
+Qed.
+
+Lemma add_cancel_r x y z : (y + x = z + x)%int63 -> y = z.
+Proof.
+ rewrite !(fun t => add_comm t x); intros Hl; apply (add_cancel_l x); auto.
+Qed.
+
+Coercion b2i (b: bool) : int := if b then 1%int63 else 0%int63.
+
+(* LSR *)
+Lemma lsr0 i : 0 >> i = 0%int63.
+Proof. apply to_Z_inj; rewrite lsr_spec; reflexivity. Qed.
+
+Lemma lsr_0_r i: i >> 0 = i.
+Proof. apply to_Z_inj; rewrite lsr_spec, Zdiv_1_r; exact eq_refl. Qed.
+
+Lemma lsr_1 n : 1 >> n = (n == 0).
+Proof.
+ case eqbP.
+ intros h; rewrite (to_Z_inj _ _ h), lsr_0_r; reflexivity.
+ intros Hn.
+ assert (H1n : (1 >> n = 0)%int63); auto.
+ apply to_Z_inj; rewrite lsr_spec.
+ apply Zdiv_small; rewrite to_Z_1; split; auto with zarith.
+ change 1%Z with (2^0)%Z.
+ apply Zpower_lt_monotone; split; auto with zarith.
+ rewrite to_Z_0 in Hn.
+ generalize (to_Z_bounded n).
+ lia.
+Qed.
+
+Lemma lsr_add i m n: ((i >> m) >> n = if n <= m + n then i >> (m + n) else 0)%int63.
+Proof.
+ case (to_Z_bounded m); intros H1m H2m.
+ case (to_Z_bounded n); intros H1n H2n.
+ case (to_Z_bounded i); intros H1i H2i.
+ generalize (add_le_r m n); case (n <= m + n)%int63; intros H.
+ apply to_Z_inj; rewrite -> !lsr_spec, Zdiv_Zdiv, <- Zpower_exp; auto with zarith.
+ rewrite add_spec, Zmod_small; auto with zarith.
+ apply to_Z_inj; rewrite -> !lsr_spec, Zdiv_Zdiv, <- Zpower_exp; auto with zarith.
+ apply Zdiv_small. split; [ auto with zarith | ].
+ eapply Z.lt_le_trans; [ | apply Zpower2_le_lin ]; auto with zarith.
+Qed.
+
+Lemma lsr_add_distr x y n: (x + y) << n = ((x << n) + (y << n))%int63.
+Proof.
+ apply to_Z_inj.
+ rewrite -> add_spec, !lsl_spec, add_spec.
+ rewrite -> Zmult_mod_idemp_l, <-Zplus_mod.
+ apply f_equal2 with (f := Zmod); auto with zarith.
+Qed.
+
+(* LSL *)
+Lemma lsl0 i: 0 << i = 0%int63.
+Proof.
+ apply to_Z_inj.
+ generalize (lsl_spec 0 i).
+ rewrite to_Z_0, Zmult_0_l, Zmod_0_l; auto.
+Qed.
+
+Lemma lsl0_r i : i << 0 = i.
+Proof.
+ apply to_Z_inj.
+ rewrite -> lsl_spec, to_Z_0, Z.mul_1_r.
+ apply Zmod_small; apply (to_Z_bounded i).
+Qed.
+
+Lemma lsl_add_distr x y n: (x + y) << n = ((x << n) + (y << n))%int63.
+Proof.
+ apply to_Z_inj; rewrite -> !lsl_spec, !add_spec, Zmult_mod_idemp_l.
+ rewrite -> !lsl_spec, <-Zplus_mod.
+ apply f_equal2 with (f := Zmod); auto with zarith.
+Qed.
+
+Lemma lsr_M_r x i (H: (digits <= i = true)%int63) : x >> i = 0%int63.
+Proof.
+ apply to_Z_inj.
+ rewrite lsr_spec, to_Z_0.
+ case (to_Z_bounded x); intros H1x H2x.
+ case (to_Z_bounded digits); intros H1d H2d.
+ rewrite -> leb_spec in H.
+ apply Zdiv_small; split; [ auto | ].
+ apply (Z.lt_le_trans _ _ _ H2x).
+ unfold wB; change (Z_of_nat size) with [|digits|].
+ apply Zpower_le_monotone; auto with zarith.
+Qed.
+
+(* BIT *)
+Lemma bit_0_spec i: [|bit i 0|] = [|i|] mod 2.
+Proof.
+ unfold bit, is_zero. rewrite lsr_0_r.
+ assert (Hbi: ([|i|] mod 2 < 2)%Z).
+ apply Z_mod_lt; auto with zarith.
+ case (to_Z_bounded i); intros H1i H2i.
+ case (Zmod_le_first [|i|] 2); auto with zarith; intros H3i H4i.
+ assert (H2b: (0 < 2 ^ [|digits - 1|])%Z).
+ apply Zpower_gt_0; auto with zarith.
+ case (to_Z_bounded (digits -1)); auto with zarith.
+ assert (H: [|i << (digits -1)|] = ([|i|] mod 2 * 2^ [|digits -1|])%Z).
+ rewrite lsl_spec.
+ rewrite -> (Z_div_mod_eq [|i|] 2) at 1; auto with zarith.
+ rewrite -> Zmult_plus_distr_l, <-Zplus_mod_idemp_l.
+ rewrite -> (Zmult_comm 2), <-Zmult_assoc.
+ replace (2 * 2 ^ [|digits - 1|])%Z with wB; auto.
+ rewrite Z_mod_mult, Zplus_0_l; apply Zmod_small.
+ split; auto with zarith.
+ replace wB with (2 * 2 ^ [|digits -1|])%Z; auto.
+ apply Zmult_lt_compat_r; auto with zarith.
+ case (Zle_lt_or_eq 0 ([|i|] mod 2)); auto with zarith; intros Hi.
+ 2: generalize H; rewrite <-Hi, Zmult_0_l.
+ 2: replace 0%Z with [|0|]; auto.
+ 2: now case eqbP.
+ generalize H; replace ([|i|] mod 2) with 1%Z; auto with zarith.
+ rewrite Zmult_1_l.
+ intros H1.
+ assert (H2: [|i << (digits - 1)|] <> [|0|]).
+ replace [|0|] with 0%Z; auto with zarith.
+ now case eqbP.
+Qed.
+
+Lemma bit_split i : ( i = (i >> 1 ) << 1 + bit i 0)%int63.
+Proof.
+ apply to_Z_inj.
+ rewrite -> add_spec, lsl_spec, lsr_spec, bit_0_spec, Zplus_mod_idemp_l.
+ replace (2 ^ [|1|]) with 2%Z; auto with zarith.
+ rewrite -> Zmult_comm, <-Z_div_mod_eq; auto with zarith.
+ rewrite Zmod_small; auto; case (to_Z_bounded i); auto.
+Qed.
+
+Lemma bit_lsr x i j :
+ (bit (x >> i) j = if j <= i + j then bit x (i + j) else false)%int63.
+Proof.
+ unfold bit; rewrite lsr_add; case (_ ≤ _); auto.
+Qed.
+
+Lemma bit_b2i (b: bool) i : bit b i = (i == 0) && b.
+Proof.
+ case b; unfold bit; simpl b2i.
+ rewrite lsr_1; case (i == 0); auto.
+ rewrite lsr0, lsl0, andb_false_r; auto.
+Qed.
+
+Lemma bit_1 n : bit 1 n = (n == 0).
+Proof.
+ unfold bit; rewrite lsr_1.
+ case (_ == _); simpl; auto.
+Qed.
+
+Local Hint Resolve Z.lt_gt Z.div_pos : zarith.
+
+Lemma to_Z_split x : [|x|] = [|(x >> 1)|] * 2 + [|bit x 0|].
+Proof.
+ case (to_Z_bounded x); intros H1x H2x.
+ case (to_Z_bounded (bit x 0)); intros H1b H2b.
+ assert (F1: 0 <= [|x >> 1|] < wB/2).
+ rewrite -> lsr_spec, to_Z_1, Z.pow_1_r. split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ rewrite -> (bit_split x) at 1.
+ rewrite -> add_spec, Zmod_small, lsl_spec, to_Z_1, Z.pow_1_r, Zmod_small;
+ split; auto with zarith.
+ change wB with ((wB/2)*2); auto with zarith.
+ rewrite -> lsl_spec, to_Z_1, Z.pow_1_r, Zmod_small; auto with zarith.
+ change wB with ((wB/2)*2); auto with zarith.
+ rewrite -> lsl_spec, to_Z_1, Z.pow_1_r, Zmod_small; auto with zarith.
+ 2: change wB with ((wB/2)*2); auto with zarith.
+ change wB with (((wB/2 - 1) * 2 + 1) + 1).
+ assert ([|bit x 0|] <= 1); auto with zarith.
+ case bit; discriminate.
+Qed.
+
+Lemma bit_M i n (H: (digits <= n = true)%int63): bit i n = false.
+Proof. unfold bit; rewrite lsr_M_r; auto. Qed.
+
+Lemma bit_half i n (H: (n < digits = true)%int63) : bit (i>>1) n = bit i (n+1).
+Proof.
+ unfold bit.
+ rewrite lsr_add.
+ case_eq (n <= (1 + n))%int63.
+ replace (1+n)%int63 with (n+1)%int63; [auto|idtac].
+ apply to_Z_inj; rewrite !add_spec, Zplus_comm; auto.
+ intros H1; assert (H2: n = max_int).
+ 2: generalize H; rewrite H2; discriminate.
+ case (to_Z_bounded n); intros H1n H2n.
+ case (Zle_lt_or_eq [|n|] (wB - 1)); auto with zarith;
+ intros H2; apply to_Z_inj; auto.
+ generalize (add_le_r 1 n); rewrite H1.
+ change [|max_int|] with (wB - 1)%Z.
+ replace [|1|] with 1%Z; auto with zarith.
+Qed.
+
+Lemma bit_ext i j : (forall n, bit i n = bit j n) -> i = j.
+Proof.
+ case (to_Z_bounded j); case (to_Z_bounded i).
+ unfold wB; revert i j; elim size.
+ simpl; intros i j ???? _; apply to_Z_inj; lia.
+ intros n ih i j.
+ rewrite Nat2Z.inj_succ, Z.pow_succ_r by auto with zarith.
+ intros hi1 hi2 hj1 hj2 hext.
+ rewrite (bit_split i), (bit_split j), hext.
+ do 2 f_equal; apply ih; clear ih.
+ 1, 3: apply to_Z_bounded.
+ 1, 2: rewrite lsr_spec; auto using Z_lt_div2.
+ intros b.
+ case (Zle_or_lt [|digits|] [|b|]).
+ rewrite <- leb_spec; intros; rewrite !bit_M; auto.
+ rewrite <- ltb_spec; intros; rewrite !bit_half; auto.
+Qed.
+
+Lemma bit_lsl x i j : bit (x << i) j =
+(if (j < i) || (digits <= j) then false else bit x (j - i))%int63.
+Proof.
+ assert (F1: 1 >= 0) by discriminate.
+ case_eq (digits <= j)%int63; intros H.
+ rewrite orb_true_r, bit_M; auto.
+ set (d := [|digits|]).
+ case (Zle_or_lt d [|j|]); intros H1.
+ case (leb_spec digits j); rewrite H; auto with zarith.
+ intros _ HH; generalize (HH H1); discriminate.
+ clear H.
+ generalize (ltb_spec j i); case ltb; intros H2; unfold bit; simpl.
+ assert (F2: ([|j|] < [|i|])%Z) by (case H2; auto); clear H2.
+ replace (is_zero (((x << i) >> j) << (digits - 1))) with true; auto.
+ case (to_Z_bounded j); intros H1j H2j.
+ apply sym_equal; rewrite is_zero_spec; apply to_Z_inj.
+ rewrite lsl_spec, lsr_spec, lsl_spec.
+ replace wB with (2^d); auto.
+ pattern d at 1; replace d with ((d - ([|j|] + 1)) + ([|j|] + 1))%Z by ring.
+ rewrite Zpower_exp; auto with zarith.
+ replace [|i|] with (([|i|] - ([|j|] + 1)) + ([|j|] + 1))%Z by ring.
+ rewrite -> Zpower_exp, Zmult_assoc; auto with zarith.
+ rewrite Zmult_mod_distr_r.
+ rewrite -> Zplus_comm, Zpower_exp, !Zmult_assoc; auto with zarith.
+ rewrite -> Z_div_mult_full; auto with zarith.
+ rewrite <-Zmult_assoc, <-Zpower_exp; auto with zarith.
+ replace (1 + [|digits - 1|])%Z with d; auto with zarith.
+ rewrite Z_mod_mult; auto.
+ case H2; intros _ H3; case (Zle_or_lt [|i|] [|j|]); intros F2.
+ 2: generalize (H3 F2); discriminate.
+ clear H2 H3.
+ apply f_equal with (f := negb).
+ apply f_equal with (f := is_zero).
+ apply to_Z_inj.
+ rewrite -> !lsl_spec, !lsr_spec, !lsl_spec.
+ pattern wB at 2 3; replace wB with (2^(1+ [|digits - 1|])); auto.
+ rewrite -> Zpower_exp, Z.pow_1_r; auto with zarith.
+ rewrite !Zmult_mod_distr_r.
+ apply f_equal2 with (f := Zmult); auto.
+ replace wB with (2^ d); auto with zarith.
+ replace d with ((d - [|i|]) + [|i|])%Z by ring.
+ case (to_Z_bounded i); intros H1i H2i.
+ rewrite Zpower_exp; auto with zarith.
+ rewrite Zmult_mod_distr_r.
+ case (to_Z_bounded j); intros H1j H2j.
+ replace [|j - i|] with ([|j|] - [|i|])%Z.
+ 2: rewrite sub_spec, Zmod_small; auto with zarith.
+ set (d1 := (d - [|i|])%Z).
+ set (d2 := ([|j|] - [|i|])%Z).
+ pattern [|j|] at 1;
+ replace [|j|] with (d2 + [|i|])%Z.
+ 2: unfold d2; ring.
+ rewrite -> Zpower_exp; auto with zarith.
+ rewrite -> Zdiv_mult_cancel_r.
+ 2: generalize (Zpower2_lt_lin [| i |] H1i); auto with zarith.
+ rewrite -> (Z_div_mod_eq [|x|] (2^d1)) at 2; auto with zarith.
+ pattern d1 at 2;
+ replace d1 with (d2 + (1+ (d - [|j|] - 1)))%Z
+ by (unfold d1, d2; ring).
+ rewrite Zpower_exp; auto with zarith.
+ rewrite <-Zmult_assoc, Zmult_comm.
+ rewrite Zdiv.Z_div_plus_full_l; auto with zarith.
+ rewrite Zpower_exp, Z.pow_1_r; auto with zarith.
+ rewrite <-Zplus_mod_idemp_l.
+ rewrite <-!Zmult_assoc, Zmult_comm, Z_mod_mult, Zplus_0_l; auto.
+Qed.
+
+(* LOR *)
+Lemma lor_lsr i1 i2 i: (i1 lor i2) >> i = (i1 >> i) lor (i2 >> i).
+Proof.
+ apply bit_ext; intros n.
+ rewrite -> lor_spec, !bit_lsr, lor_spec.
+ case (_ <= _)%int63; auto.
+Qed.
+
+Lemma lor_le x y : (y <= x lor y)%int63 = true.
+Proof.
+ generalize x y (to_Z_bounded x) (to_Z_bounded y); clear x y.
+ unfold wB; elim size.
+ replace (2^Z_of_nat 0) with 1%Z; auto with zarith.
+ intros x y Hx Hy; replace x with 0%int63.
+ replace y with 0%int63; auto.
+ apply to_Z_inj; rewrite to_Z_0; auto with zarith.
+ apply to_Z_inj; rewrite to_Z_0; auto with zarith.
+ intros n IH x y; rewrite inj_S.
+ unfold Z.succ; rewrite -> Zpower_exp, Z.pow_1_r; auto with zarith.
+ intros Hx Hy.
+ rewrite leb_spec.
+ rewrite -> (to_Z_split y) at 1; rewrite (to_Z_split (x lor y)).
+ assert ([|y>>1|] <= [|(x lor y) >> 1|]).
+ rewrite -> lor_lsr, <-leb_spec; apply IH.
+ rewrite -> lsr_spec, to_Z_1, Z.pow_1_r; split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ rewrite -> lsr_spec, to_Z_1, Z.pow_1_r; split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ assert ([|bit y 0|] <= [|bit (x lor y) 0|]); auto with zarith.
+ rewrite lor_spec; do 2 case bit; try discriminate.
+Qed.
+
+Lemma bit_0 n : bit 0 n = false.
+Proof. unfold bit; rewrite lsr0; auto. Qed.
+
+Lemma bit_add_or x y:
+ (forall n, bit x n = true -> bit y n = true -> False) <-> (x + y)%int63= x lor y.
+Proof.
+ generalize x y (to_Z_bounded x) (to_Z_bounded y); clear x y.
+ unfold wB; elim size.
+ replace (2^Z_of_nat 0) with 1%Z; auto with zarith.
+ intros x y Hx Hy; replace x with 0%int63.
+ replace y with 0%int63.
+ split; auto; intros _ n; rewrite !bit_0; discriminate.
+ apply to_Z_inj; rewrite to_Z_0; auto with zarith.
+ apply to_Z_inj; rewrite to_Z_0; auto with zarith.
+ intros n IH x y; rewrite inj_S.
+ unfold Z.succ; rewrite Zpower_exp, Z.pow_1_r; auto with zarith.
+ intros Hx Hy.
+ split.
+ intros Hn.
+ assert (F1: ((x >> 1) + (y >> 1))%int63 = (x >> 1) lor (y >> 1)).
+ apply IH.
+ rewrite lsr_spec, Z.pow_1_r; split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ rewrite lsr_spec, Z.pow_1_r; split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ intros m H1 H2.
+ case_eq (digits <= m)%int63; [idtac | rewrite <- not_true_iff_false];
+ intros Heq.
+ rewrite bit_M in H1; auto; discriminate.
+ rewrite leb_spec in Heq.
+ apply (Hn (m + 1)%int63);
+ rewrite <-bit_half; auto; rewrite ltb_spec; auto with zarith.
+ rewrite (bit_split (x lor y)), lor_lsr, <- F1, lor_spec.
+ replace (b2i (bit x 0 || bit y 0)) with (bit x 0 + bit y 0)%int63.
+ 2: generalize (Hn 0%int63); do 2 case bit; auto; intros [ ]; auto.
+ rewrite lsl_add_distr.
+ rewrite (bit_split x) at 1; rewrite (bit_split y) at 1.
+ rewrite <-!add_assoc; apply f_equal2 with (f := add); auto.
+ rewrite add_comm, <-!add_assoc; apply f_equal2 with (f := add); auto.
+ rewrite add_comm; auto.
+ intros Heq.
+ generalize (add_le_r x y); rewrite Heq, lor_le; intro Hb.
+ generalize Heq; rewrite (bit_split x) at 1; rewrite (bit_split y )at 1; clear Heq.
+ rewrite (fun y => add_comm y (bit x 0)), <-!add_assoc, add_comm,
+ <-!add_assoc, (add_comm (bit y 0)), add_assoc, <-lsr_add_distr.
+ rewrite (bit_split (x lor y)), lor_spec.
+ intros Heq.
+ assert (F: (bit x 0 + bit y 0)%int63 = (bit x 0 || bit y 0)).
+ assert (F1: (2 | wB)) by (apply Zpower_divide; apply refl_equal).
+ assert (F2: 0 < wB) by (apply refl_equal).
+ assert (F3: [|bit x 0 + bit y 0|] mod 2 = [|bit x 0 || bit y 0|] mod 2).
+ apply trans_equal with (([|(x>>1 + y>>1) << 1|] + [|bit x 0 + bit y 0|]) mod 2).
+ rewrite lsl_spec, Zplus_mod, <-Zmod_div_mod; auto with zarith.
+ rewrite Z.pow_1_r, Z_mod_mult, Zplus_0_l, Zmod_mod; auto with zarith.
+ rewrite (Zmod_div_mod 2 wB), <-add_spec, Heq; auto with zarith.
+ rewrite add_spec, <-Zmod_div_mod; auto with zarith.
+ rewrite lsl_spec, Zplus_mod, <-Zmod_div_mod; auto with zarith.
+ rewrite Z.pow_1_r, Z_mod_mult, Zplus_0_l, Zmod_mod; auto with zarith.
+ generalize F3; do 2 case bit; try discriminate; auto.
+ case (IH (x >> 1) (y >> 1)).
+ rewrite lsr_spec, to_Z_1, Z.pow_1_r; split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ rewrite lsr_spec, to_Z_1, Z.pow_1_r; split; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ intros _ HH m; case (to_Z_bounded m); intros H1m H2m.
+ case_eq (digits <= m)%int63.
+ intros Hlm; rewrite bit_M; auto; discriminate.
+ rewrite <- not_true_iff_false, leb_spec; intros Hlm.
+ case (Zle_lt_or_eq 0 [|m|]); auto; intros Hm.
+ replace m with ((m -1) + 1)%int63.
+ rewrite <-(bit_half x), <-(bit_half y); auto with zarith.
+ apply HH.
+ rewrite <-lor_lsr.
+ assert (0 <= [|bit (x lor y) 0|] <= 1) by (case bit; split; discriminate).
+ rewrite F in Heq; generalize (add_cancel_r _ _ _ Heq).
+ intros Heq1; apply to_Z_inj.
+ generalize (f_equal to_Z Heq1); rewrite lsl_spec, to_Z_1, Z.pow_1_r, Zmod_small.
+ rewrite lsl_spec, to_Z_1, Z.pow_1_r, Zmod_small; auto with zarith.
+ case (to_Z_bounded (x lor y)); intros H1xy H2xy.
+ rewrite lsr_spec, to_Z_1, Z.pow_1_r; auto with zarith.
+ change wB with ((wB/2)*2); split; auto with zarith.
+ assert ([|x lor y|] / 2 < wB / 2); auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ split.
+ case (to_Z_bounded (x >> 1 + y >> 1)); auto with zarith.
+ rewrite add_spec.
+ apply Z.le_lt_trans with (([|x >> 1|] + [|y >> 1|]) * 2); auto with zarith.
+ case (Zmod_le_first ([|x >> 1|] + [|y >> 1|]) wB); auto with zarith.
+ case (to_Z_bounded (x >> 1)); case (to_Z_bounded (y >> 1)); auto with zarith.
+ generalize Hb; rewrite (to_Z_split x) at 1; rewrite (to_Z_split y) at 1.
+ case (to_Z_bounded (bit x 0)); case (to_Z_bounded (bit y 0)); auto with zarith.
+ rewrite ltb_spec, sub_spec, to_Z_1, Zmod_small; auto with zarith.
+ rewrite ltb_spec, sub_spec, to_Z_1, Zmod_small; auto with zarith.
+ apply to_Z_inj.
+ rewrite add_spec, sub_spec, Zplus_mod_idemp_l, to_Z_1, Zmod_small; auto with zarith.
+ pose proof (to_Z_inj 0 _ Hm); clear Hm; subst m.
+ intros hx hy; revert F; rewrite hx, hy; intros F. generalize (f_equal to_Z F). vm_compute. lia.
+Qed.
+
+Lemma addmuldiv_spec x y p :
+ [| p |] <= [| digits |] ->
+ [| addmuldiv p x y |] = ([| x |] * (2 ^ [| p |]) + [| y |] / (2 ^ ([| digits |] - [| p |]))) mod wB.
+Proof.
+ intros H.
+ assert (Fp := to_Z_bounded p); assert (Fd := to_Z_bounded digits).
+ rewrite addmuldiv_def_spec; unfold addmuldiv_def.
+ case (bit_add_or (x << p) (y >> (digits - p))); intros HH _.
+ rewrite <-HH, add_spec, lsl_spec, lsr_spec, Zplus_mod_idemp_l, sub_spec.
+ rewrite (fun x y => Zmod_small (x - y)); auto with zarith.
+ intros n; rewrite -> bit_lsl, bit_lsr.
+ generalize (add_le_r (digits - p) n).
+ case (_ ≤ _); try discriminate.
+ rewrite -> sub_spec, Zmod_small; auto with zarith; intros H1.
+ case_eq (n < p)%int63; try discriminate.
+ rewrite <- not_true_iff_false, ltb_spec; intros H2.
+ case (_ ≤ _); try discriminate.
+ intros _; rewrite bit_M; try discriminate.
+ rewrite -> leb_spec, add_spec, Zmod_small, sub_spec, Zmod_small; auto with zarith.
+ rewrite -> sub_spec, Zmod_small; auto with zarith.
+Qed.
+
+(* is_even *)
+Lemma is_even_bit i : is_even i = negb (bit i 0).
+Proof.
+ unfold is_even.
+ replace (i land 1) with (b2i (bit i 0)).
+ case bit; auto.
+ apply bit_ext; intros n.
+ rewrite bit_b2i, land_spec, bit_1.
+ generalize (eqb_spec n 0).
+ case (n == 0); auto.
+ intros(H,_); rewrite andb_true_r, H; auto.
+ rewrite andb_false_r; auto.
+Qed.
+
+Lemma is_even_spec x : if is_even x then [|x|] mod 2 = 0 else [|x|] mod 2 = 1.
+Proof.
+rewrite is_even_bit.
+generalize (bit_0_spec x); case bit; simpl; auto.
+Qed.
+
+Lemma is_even_0 : is_even 0 = true.
+Proof. apply refl_equal. Qed.
+
+Lemma is_even_lsl_1 i : is_even (i << 1) = true.
+Proof.
+ rewrite is_even_bit, bit_lsl; auto.
+Qed.
+
+(* Sqrt *)
+
+ (* Direct transcription of an old proof
+ of a fortran program in boyer-moore *)
+
+Ltac elim_div :=
+ unfold Z.div, Z.modulo;
+ match goal with
+ | H : context[ Z.div_eucl ?X ?Y ] |- _ =>
+ generalize dependent H; generalize (Z_div_mod_full X Y) ; case (Z.div_eucl X Y)
+ | |- context[ Z.div_eucl ?X ?Y ] =>
+ generalize (Z_div_mod_full X Y) ; case (Z.div_eucl X Y)
+ end; unfold Remainder.
+
+Lemma quotient_by_2 a: a - 1 <= (a/2) + (a/2).
+Proof.
+ case (Z_mod_lt a 2); auto with zarith.
+ intros H1; rewrite Zmod_eq_full; auto with zarith.
+Qed.
+
+Lemma sqrt_main_trick j k: 0 <= j -> 0 <= k ->
+ (j * k) + j <= ((j + k)/2 + 1) ^ 2.
+Proof.
+ intros Hj; generalize Hj k; pattern j; apply natlike_ind;
+ auto; clear k j Hj.
+ intros _ k Hk; repeat rewrite Zplus_0_l.
+ apply Zmult_le_0_compat; generalize (Z_div_pos k 2); auto with zarith.
+ intros j Hj Hrec _ k Hk; pattern k; apply natlike_ind; auto; clear k Hk.
+ rewrite -> Zmult_0_r, Zplus_0_r, Zplus_0_l.
+ generalize (sqr_pos (Z.succ j / 2)) (quotient_by_2 (Z.succ j));
+ unfold Z.succ.
+ rewrite Z.pow_2_r, Zmult_plus_distr_l; repeat rewrite Zmult_plus_distr_r.
+ auto with zarith.
+ intros k Hk _.
+ replace ((Z.succ j + Z.succ k) / 2) with ((j + k)/2 + 1).
+ generalize (Hrec Hj k Hk) (quotient_by_2 (j + k)).
+ unfold Z.succ; repeat rewrite Z.pow_2_r;
+ repeat rewrite Zmult_plus_distr_l; repeat rewrite Zmult_plus_distr_r.
+ repeat rewrite Zmult_1_l; repeat rewrite Zmult_1_r.
+ auto with zarith.
+ rewrite -> Zplus_comm, <- Z_div_plus_full_l; auto with zarith.
+ apply f_equal2; auto with zarith.
+Qed.
+
+Lemma sqrt_main i j: 0 <= i -> 0 < j -> i < ((j + (i/j))/2 + 1) ^ 2.
+Proof.
+ intros Hi Hj.
+ assert (Hij: 0 <= i/j) by (apply Z_div_pos; auto with zarith).
+ refine (Z.lt_le_trans _ _ _ _ (sqrt_main_trick _ _ (Zlt_le_weak _ _ Hj) Hij)).
+ pattern i at 1; rewrite -> (Z_div_mod_eq i j); case (Z_mod_lt i j); auto with zarith.
+Qed.
+
+Lemma sqrt_test_false i j: 0 <= i -> 0 < j -> i/j < j -> (j + (i/j))/2 < j.
+Proof.
+ intros Hi Hj; elim_div; intros q r [ ? hr ]; [ lia | subst i ].
+ elim_div; intros a b [ h [ hb | ] ]; lia.
+Qed.
+
+Lemma sqrt_test_true i j: 0 <= i -> 0 < j -> i/j >= j -> j ^ 2 <= i.
+Proof.
+ intros Hi Hj Hd; rewrite Z.pow_2_r.
+ apply Z.le_trans with (j * (i/j)); auto with zarith.
+ apply Z_mult_div_ge; auto with zarith.
+Qed.
+
+Lemma sqrt_step_correct rec i j:
+ 0 < [|i|] -> 0 < [|j|] -> [|i|] < ([|j|] + 1) ^ 2 ->
+ 2 * [|j|] < wB ->
+ (forall j1 : int,
+ 0 < [|j1|] < [|j|] -> [|i|] < ([|j1|] + 1) ^ 2 ->
+ [|rec i j1|] ^ 2 <= [|i|] < ([|rec i j1|] + 1) ^ 2) ->
+ [|sqrt_step rec i j|] ^ 2 <= [|i|] < ([|sqrt_step rec i j|] + 1) ^ 2.
+Proof.
+ assert (Hp2: 0 < [|2|]) by exact (refl_equal Lt).
+ intros Hi Hj Hij H31 Hrec.
+ unfold sqrt_step.
+ case ltbP; rewrite div_spec.
+ - intros hlt.
+ assert ([| j + i / j|] = [|j|] + [|i|]/[|j|]) as hj.
+ rewrite add_spec, Zmod_small;rewrite div_spec; auto with zarith.
+ apply Hrec; rewrite lsr_spec, hj, to_Z_1; change (2 ^ 1) with 2.
+ + split; [ | apply sqrt_test_false;auto with zarith].
+ replace ([|j|] + [|i|]/[|j|]) with (1 * 2 + (([|j|] - 2) + [|i|] / [|j|])) by ring.
+ rewrite Z_div_plus_full_l; auto with zarith.
+ assert (0 <= [|i|]/ [|j|]) by (apply Z_div_pos; auto with zarith).
+ assert (0 <= ([|j|] - 2 + [|i|] / [|j|]) / 2) ; auto with zarith.
+ apply Z.div_pos; [ | lia ].
+ case (Zle_lt_or_eq 1 [|j|]); auto with zarith; intros Hj1.
+ rewrite <- Hj1, Zdiv_1_r; lia.
+ + apply sqrt_main;auto with zarith.
+ - split;[apply sqrt_test_true | ];auto with zarith.
+Qed.
+
+Lemma iter_sqrt_correct n rec i j: 0 < [|i|] -> 0 < [|j|] ->
+ [|i|] < ([|j|] + 1) ^ 2 -> 2 * [|j|] < wB ->
+ (forall j1, 0 < [|j1|] -> 2^(Z_of_nat n) + [|j1|] <= [|j|] ->
+ [|i|] < ([|j1|] + 1) ^ 2 -> 2 * [|j1|] < wB ->
+ [|rec i j1|] ^ 2 <= [|i|] < ([|rec i j1|] + 1) ^ 2) ->
+ [|iter_sqrt n rec i j|] ^ 2 <= [|i|] < ([|iter_sqrt n rec i j|] + 1) ^ 2.
+Proof.
+ revert rec i j; elim n; unfold iter_sqrt; fold iter_sqrt; clear n.
+ intros rec i j Hi Hj Hij H31 Hrec; apply sqrt_step_correct; auto with zarith.
+ intros; apply Hrec; auto with zarith.
+ rewrite Zpower_0_r; auto with zarith.
+ intros n Hrec rec i j Hi Hj Hij H31 HHrec.
+ apply sqrt_step_correct; auto.
+ intros j1 Hj1 Hjp1; apply Hrec; auto with zarith.
+ intros j2 Hj2 H2j2 Hjp2 Hj31; apply Hrec; auto with zarith.
+ intros j3 Hj3 Hpj3.
+ apply HHrec; auto.
+ rewrite -> inj_S, Z.pow_succ_r.
+ apply Z.le_trans with (2 ^Z_of_nat n + [|j2|]); auto with zarith.
+ apply Zle_0_nat.
+Qed.
+
+Lemma sqrt_init i: 1 < i -> i < (i/2 + 1) ^ 2.
+Proof.
+ intros Hi.
+ assert (H1: 0 <= i - 2) by auto with zarith.
+ assert (H2: 1 <= (i / 2) ^ 2); auto with zarith.
+ replace i with (1* 2 + (i - 2)); auto with zarith.
+ rewrite Z.pow_2_r, Z_div_plus_full_l; auto with zarith.
+ generalize (sqr_pos ((i - 2)/ 2)) (Z_div_pos (i - 2) 2).
+ rewrite Zmult_plus_distr_l; repeat rewrite Zmult_plus_distr_r.
+ auto with zarith.
+ generalize (quotient_by_2 i).
+ rewrite -> Z.pow_2_r in H2 |- *;
+ repeat (rewrite Zmult_plus_distr_l ||
+ rewrite Zmult_plus_distr_r ||
+ rewrite Zmult_1_l || rewrite Zmult_1_r).
+ auto with zarith.
+Qed.
+
+Lemma sqrt_spec : forall x,
+ [|sqrt x|] ^ 2 <= [|x|] < ([|sqrt x|] + 1) ^ 2.
+Proof.
+ intros i; unfold sqrt.
+ rewrite compare_spec. case Z.compare_spec; rewrite to_Z_1;
+ intros Hi; auto with zarith.
+ repeat rewrite Z.pow_2_r; auto with zarith.
+ apply iter_sqrt_correct; auto with zarith;
+ rewrite lsr_spec, to_Z_1; change (2^1) with 2; auto with zarith.
+ replace [|i|] with (1 * 2 + ([|i|] - 2))%Z; try ring.
+ assert (0 <= ([|i|] - 2)/2)%Z by (apply Z_div_pos; auto with zarith).
+ rewrite Z_div_plus_full_l; auto with zarith.
+ apply sqrt_init; auto.
+ assert (W:= Z_mult_div_ge [|i|] 2);assert (W':= to_Z_bounded i);auto with zarith.
+ intros j2 H1 H2; contradict H2; apply Zlt_not_le.
+ fold wB;assert (W:=to_Z_bounded i).
+ apply Z.le_lt_trans with ([|i|]); auto with zarith.
+ assert (0 <= [|i|]/2)%Z by (apply Z_div_pos; auto with zarith).
+ apply Z.le_trans with (2 * ([|i|]/2)); auto with zarith.
+ apply Z_mult_div_ge; auto with zarith.
+ case (to_Z_bounded i); repeat rewrite Z.pow_2_r; auto with zarith.
+Qed.
+
+(* sqrt2 *)
+Lemma sqrt2_step_def rec ih il j:
+ sqrt2_step rec ih il j =
+ if (ih < j)%int63 then
+ let quo := fst (diveucl_21 ih il j) in
+ if (quo < j)%int63 then
+ let m :=
+ match j +c quo with
+ | C0 m1 => m1 >> 1
+ | C1 m1 => (m1 >> 1 + 1 << (digits -1))%int63
+ end in
+ rec ih il m
+ else j
+ else j.
+Proof.
+ unfold sqrt2_step; case diveucl_21; intros;simpl.
+ case (j +c i);trivial.
+Qed.
+
+Lemma sqrt2_lower_bound ih il j:
+ [|| WW ih il||] < ([|j|] + 1) ^ 2 -> [|ih|] <= [|j|].
+Proof.
+ intros H1.
+ case (to_Z_bounded j); intros Hbj _.
+ case (to_Z_bounded il); intros Hbil _.
+ case (to_Z_bounded ih); intros Hbih Hbih1.
+ assert (([|ih|] < [|j|] + 1)%Z); auto with zarith.
+ apply Zlt_square_simpl; auto with zarith.
+ simpl zn2z_to_Z in H1.
+ repeat rewrite <-Z.pow_2_r.
+ refine (Z.le_lt_trans _ _ _ _ H1).
+ apply Z.le_trans with ([|ih|] * wB)%Z;try rewrite Z.pow_2_r; auto with zarith.
+Qed.
+
+Lemma div2_phi ih il j:
+ [|fst (diveucl_21 ih il j)|] = [|| WW ih il||] /[|j|].
+Proof.
+ generalize (diveucl_21_spec ih il j).
+ case diveucl_21; intros q r Heq.
+ simpl zn2z_to_Z;unfold Z.div;rewrite <- Heq;trivial.
+Qed.
+
+Lemma sqrt2_step_correct rec ih il j:
+ 2 ^ (Z_of_nat (size - 2)) <= [|ih|] ->
+ 0 < [|j|] -> [|| WW ih il||] < ([|j|] + 1) ^ 2 ->
+ (forall j1, 0 < [|j1|] < [|j|] -> [|| WW ih il||] < ([|j1|] + 1) ^ 2 ->
+ [|rec ih il j1|] ^ 2 <= [||WW ih il||] < ([|rec ih il j1|] + 1) ^ 2) ->
+ [|sqrt2_step rec ih il j|] ^ 2 <= [||WW ih il ||]
+ < ([|sqrt2_step rec ih il j|] + 1) ^ 2.
+Proof.
+ assert (Hp2: (0 < [|2|])%Z) by exact (refl_equal Lt).
+ intros Hih Hj Hij Hrec; rewrite sqrt2_step_def.
+ assert (H1: ([|ih|] <= [|j|])%Z) by (apply sqrt2_lower_bound with il; auto).
+ case (to_Z_bounded ih); intros Hih1 _.
+ case (to_Z_bounded il); intros Hil1 _.
+ case (to_Z_bounded j); intros _ Hj1.
+ assert (Hp3: (0 < [||WW ih il||])).
+ simpl zn2z_to_Z;apply Z.lt_le_trans with ([|ih|] * wB)%Z; auto with zarith.
+ apply Zmult_lt_0_compat; auto with zarith.
+ refine (Z.lt_le_trans _ _ _ _ Hih); auto with zarith.
+ cbv zeta.
+ case_eq (ih < j)%int63;intros Heq.
+ rewrite -> ltb_spec in Heq.
+ 2: rewrite <-not_true_iff_false, ltb_spec in Heq.
+ 2: split; auto.
+ 2: apply sqrt_test_true; auto with zarith.
+ 2: unfold zn2z_to_Z; replace [|ih|] with [|j|]; auto with zarith.
+ 2: assert (0 <= [|il|]/[|j|]) by (apply Z_div_pos; auto with zarith).
+ 2: rewrite Zmult_comm, Z_div_plus_full_l; unfold base; auto with zarith.
+ case (Zle_or_lt (2^(Z_of_nat size -1)) [|j|]); intros Hjj.
+ case_eq (fst (diveucl_21 ih il j) < j)%int63;intros Heq0.
+ 2: rewrite <-not_true_iff_false, ltb_spec, div2_phi in Heq0.
+ 2: split; auto; apply sqrt_test_true; auto with zarith.
+ rewrite -> ltb_spec, div2_phi in Heq0.
+ match goal with |- context[rec _ _ ?X] =>
+ set (u := X)
+ end.
+ assert (H: [|u|] = ([|j|] + ([||WW ih il||])/([|j|]))/2).
+ unfold u; generalize (addc_spec j (fst (diveucl_21 ih il j)));
+ case addc;unfold interp_carry;rewrite div2_phi;simpl zn2z_to_Z.
+ intros i H;rewrite lsr_spec, H;trivial.
+ intros i H;rewrite <- H.
+ case (to_Z_bounded i); intros H1i H2i.
+ rewrite -> add_spec, Zmod_small, lsr_spec.
+ change (1 * wB) with ([|(1 << (digits -1))|] * 2)%Z.
+ rewrite Z_div_plus_full_l; auto with zarith.
+ change wB with (2 * (wB/2))%Z; auto.
+ replace [|(1 << (digits - 1))|] with (wB/2); auto.
+ rewrite lsr_spec; auto.
+ replace (2^[|1|]) with 2%Z; auto.
+ split; auto with zarith.
+ assert ([|i|]/2 < wB/2); auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ apply Hrec; rewrite H; clear u H.
+ assert (Hf1: 0 <= [||WW ih il||]/ [|j|]) by (apply Z_div_pos; auto with zarith).
+ case (Zle_lt_or_eq 1 ([|j|])); auto with zarith; intros Hf2.
+ 2: contradict Heq0; apply Zle_not_lt; rewrite <- Hf2, Zdiv_1_r; auto with zarith.
+ split.
+ replace ([|j|] + [||WW ih il||]/ [|j|])%Z with
+ (1 * 2 + (([|j|] - 2) + [||WW ih il||] / [|j|])) by lia.
+ rewrite Z_div_plus_full_l; auto with zarith.
+ assert (0 <= ([|j|] - 2 + [||WW ih il||] / [|j|]) / 2) ; auto with zarith.
+ apply sqrt_test_false; auto with zarith.
+ apply sqrt_main; auto with zarith.
+ contradict Hij; apply Zle_not_lt.
+ assert ((1 + [|j|]) <= 2 ^ (Z_of_nat size - 1)); auto with zarith.
+ apply Z.le_trans with ((2 ^ (Z_of_nat size - 1)) ^2); auto with zarith.
+ assert (0 <= 1 + [|j|]); auto with zarith.
+ apply Zmult_le_compat; auto with zarith.
+ change ((2 ^ (Z_of_nat size - 1))^2) with (2 ^ (Z_of_nat size - 2) * wB).
+ apply Z.le_trans with ([|ih|] * wB); auto with zarith.
+ unfold zn2z_to_Z, wB; auto with zarith.
+Qed.
+
+Lemma iter2_sqrt_correct n rec ih il j:
+ 2^(Z_of_nat (size - 2)) <= [|ih|] -> 0 < [|j|] -> [||WW ih il||] < ([|j|] + 1) ^ 2 ->
+ (forall j1, 0 < [|j1|] -> 2^(Z_of_nat n) + [|j1|] <= [|j|] ->
+ [||WW ih il||] < ([|j1|] + 1) ^ 2 ->
+ [|rec ih il j1|] ^ 2 <= [||WW ih il||] < ([|rec ih il j1|] + 1) ^ 2) ->
+ [|iter2_sqrt n rec ih il j|] ^ 2 <= [||WW ih il||]
+ < ([|iter2_sqrt n rec ih il j|] + 1) ^ 2.
+Proof.
+ revert rec ih il j; elim n; unfold iter2_sqrt; fold iter2_sqrt; clear n.
+ intros rec ih il j Hi Hj Hij Hrec; apply sqrt2_step_correct; auto with zarith.
+ intros; apply Hrec; auto with zarith.
+ rewrite Zpower_0_r; auto with zarith.
+ intros n Hrec rec ih il j Hi Hj Hij HHrec.
+ apply sqrt2_step_correct; auto.
+ intros j1 Hj1 Hjp1; apply Hrec; auto with zarith.
+ intros j2 Hj2 H2j2 Hjp2; apply Hrec; auto with zarith.
+ intros j3 Hj3 Hpj3.
+ apply HHrec; auto.
+ rewrite -> inj_S, Z.pow_succ_r.
+ apply Z.le_trans with (2 ^Z_of_nat n + [|j2|])%Z; auto with zarith.
+ apply Zle_0_nat.
+Qed.
+
+Lemma sqrt2_spec : forall x y,
+ wB/ 4 <= [|x|] ->
+ let (s,r) := sqrt2 x y in
+ [||WW x y||] = [|s|] ^ 2 + [+|r|] /\
+ [+|r|] <= 2 * [|s|].
+ Proof.
+ intros ih il Hih; unfold sqrt2.
+ change [||WW ih il||] with ([||WW ih il||]).
+ assert (Hbin: forall s, s * s + 2* s + 1 = (s + 1) ^ 2) by
+ (intros s; ring).
+ assert (Hb: 0 <= wB) by (red; intros HH; discriminate).
+ assert (Hi2: [||WW ih il ||] < ([|max_int|] + 1) ^ 2).
+ apply Z.le_lt_trans with ((wB - 1) * wB + (wB - 1)); auto with zarith.
+ 2: apply refl_equal.
+ case (to_Z_bounded ih); case (to_Z_bounded il); intros H1 H2 H3 H4.
+ unfold zn2z_to_Z; auto with zarith.
+ case (iter2_sqrt_correct size (fun _ _ j => j) ih il max_int); auto with zarith.
+ apply refl_equal.
+ intros j1 _ HH; contradict HH.
+ apply Zlt_not_le.
+ case (to_Z_bounded j1); auto with zarith.
+ change (2 ^ Z_of_nat size) with ([|max_int|]+1)%Z; auto with zarith.
+ set (s := iter2_sqrt size (fun _ _ j : int=> j) ih il max_int).
+ intros Hs1 Hs2.
+ generalize (mulc_spec s s); case mulc.
+ simpl fst; simpl snd; intros ih1 il1 Hihl1.
+ generalize (subc_spec il il1).
+ case subc; intros il2 Hil2.
+ simpl interp_carry in Hil2.
+ case_eq (ih1 < ih)%int63; [idtac | rewrite <- not_true_iff_false];
+ rewrite ltb_spec; intros Heq.
+ unfold interp_carry; rewrite Zmult_1_l.
+ rewrite -> Z.pow_2_r, Hihl1, Hil2.
+ case (Zle_lt_or_eq ([|ih1|] + 1) ([|ih|])); auto with zarith.
+ intros H2; contradict Hs2; apply Zle_not_lt.
+ replace (([|s|] + 1) ^ 2) with ([||WW ih1 il1||] + 2 * [|s|] + 1).
+ unfold zn2z_to_Z.
+ case (to_Z_bounded il); intros Hpil _.
+ assert (Hl1l: [|il1|] <= [|il|]).
+ case (to_Z_bounded il2); rewrite Hil2; auto with zarith.
+ assert ([|ih1|] * wB + 2 * [|s|] + 1 <= [|ih|] * wB); auto with zarith.
+ case (to_Z_bounded s); intros _ Hps.
+ case (to_Z_bounded ih1); intros Hpih1 _; auto with zarith.
+ apply Z.le_trans with (([|ih1|] + 2) * wB); auto with zarith.
+ rewrite Zmult_plus_distr_l.
+ assert (2 * [|s|] + 1 <= 2 * wB); auto with zarith.
+ unfold zn2z_to_Z; rewrite <-Hihl1, Hbin; auto.
+ intros H2; split.
+ unfold zn2z_to_Z; rewrite <- H2; ring.
+ replace (wB + ([|il|] - [|il1|])) with ([||WW ih il||] - ([|s|] * [|s|])).
+ rewrite <-Hbin in Hs2; auto with zarith.
+ rewrite Hihl1; unfold zn2z_to_Z; rewrite <- H2; ring.
+ unfold interp_carry.
+ case (Zle_lt_or_eq [|ih|] [|ih1|]); auto with zarith; intros H.
+ contradict Hs1.
+ apply Zlt_not_le; rewrite Z.pow_2_r, Hihl1.
+ unfold zn2z_to_Z.
+ case (to_Z_bounded il); intros _ H2.
+ apply Z.lt_le_trans with (([|ih|] + 1) * wB + 0).
+ rewrite Zmult_plus_distr_l, Zplus_0_r; auto with zarith.
+ case (to_Z_bounded il1); intros H3 _.
+ apply Zplus_le_compat; auto with zarith.
+ split.
+ rewrite Z.pow_2_r, Hihl1.
+ unfold zn2z_to_Z; ring[Hil2 H].
+ replace [|il2|] with ([||WW ih il||] - [||WW ih1 il1||]).
+ unfold zn2z_to_Z at 2; rewrite <-Hihl1.
+ rewrite <-Hbin in Hs2; auto with zarith.
+ unfold zn2z_to_Z; rewrite H, Hil2; ring.
+ unfold interp_carry in Hil2 |- *.
+ assert (Hsih: [|ih - 1|] = [|ih|] - 1).
+ rewrite sub_spec, Zmod_small; auto; replace [|1|] with 1; auto.
+ case (to_Z_bounded ih); intros H1 H2.
+ split; auto with zarith.
+ apply Z.le_trans with (wB/4 - 1); auto with zarith.
+ case_eq (ih1 < ih - 1)%int63; [idtac | rewrite <- not_true_iff_false];
+ rewrite ltb_spec, Hsih; intros Heq.
+ rewrite Z.pow_2_r, Hihl1.
+ case (Zle_lt_or_eq ([|ih1|] + 2) [|ih|]); auto with zarith.
+ intros H2; contradict Hs2; apply Zle_not_lt.
+ replace (([|s|] + 1) ^ 2) with ([||WW ih1 il1||] + 2 * [|s|] + 1).
+ unfold zn2z_to_Z.
+ assert ([|ih1|] * wB + 2 * [|s|] + 1 <= [|ih|] * wB + ([|il|] - [|il1|]));
+ auto with zarith.
+ rewrite <-Hil2.
+ case (to_Z_bounded il2); intros Hpil2 _.
+ apply Z.le_trans with ([|ih|] * wB + - wB); auto with zarith.
+ case (to_Z_bounded s); intros _ Hps.
+ assert (2 * [|s|] + 1 <= 2 * wB); auto with zarith.
+ apply Z.le_trans with ([|ih1|] * wB + 2 * wB); auto with zarith.
+ assert (Hi: ([|ih1|] + 3) * wB <= [|ih|] * wB); auto with zarith.
+ rewrite Zmult_plus_distr_l in Hi; auto with zarith.
+ unfold zn2z_to_Z; rewrite <-Hihl1, Hbin; auto.
+ intros H2; unfold zn2z_to_Z; rewrite <-H2.
+ split.
+ replace [|il|] with (([|il|] - [|il1|]) + [|il1|]); try ring.
+ rewrite <-Hil2; ring.
+ replace (1 * wB + [|il2|]) with ([||WW ih il||] - [||WW ih1 il1||]).
+ unfold zn2z_to_Z at 2; rewrite <-Hihl1.
+ rewrite <-Hbin in Hs2; auto with zarith.
+ unfold zn2z_to_Z; rewrite <-H2.
+ replace [|il|] with (([|il|] - [|il1|]) + [|il1|]); try ring.
+ rewrite <-Hil2; ring.
+ case (Zle_lt_or_eq ([|ih|] - 1) ([|ih1|])); auto with zarith; intros H1.
+ assert (He: [|ih|] = [|ih1|]).
+ apply Zle_antisym; auto with zarith.
+ case (Zle_or_lt [|ih1|] [|ih|]); auto; intros H2.
+ contradict Hs1; apply Zlt_not_le; rewrite Z.pow_2_r, Hihl1.
+ unfold zn2z_to_Z.
+ case (to_Z_bounded il); intros _ Hpil1.
+ apply Z.lt_le_trans with (([|ih|] + 1) * wB).
+ rewrite Zmult_plus_distr_l, Zmult_1_l; auto with zarith.
+ case (to_Z_bounded il1); intros Hpil2 _.
+ apply Z.le_trans with (([|ih1|]) * wB); auto with zarith.
+ contradict Hs1; apply Zlt_not_le; rewrite Z.pow_2_r, Hihl1.
+ unfold zn2z_to_Z; rewrite He.
+ assert ([|il|] - [|il1|] < 0); auto with zarith.
+ rewrite <-Hil2.
+ case (to_Z_bounded il2); auto with zarith.
+ split.
+ rewrite Z.pow_2_r, Hihl1.
+ unfold zn2z_to_Z; rewrite <-H1.
+ apply trans_equal with ([|ih|] * wB + [|il1|] + ([|il|] - [|il1|])).
+ ring.
+ rewrite <-Hil2; ring.
+ replace [|il2|] with ([||WW ih il||] - [||WW ih1 il1||]).
+ unfold zn2z_to_Z at 2; rewrite <- Hihl1.
+ rewrite <-Hbin in Hs2; auto with zarith.
+ unfold zn2z_to_Z.
+ rewrite <-H1.
+ ring_simplify.
+ apply trans_equal with (wB + ([|il|] - [|il1|])).
+ ring.
+ rewrite <-Hil2; ring.
+Qed.
+
+(* of_pos *)
+Lemma of_pos_rec_spec (k: nat) :
+ (k <= size)%nat →
+ ∀ p, φ(of_pos_rec k p) = Zpos p mod 2 ^ Z.of_nat k.
+Proof.
+ elim k; clear k.
+ intros _ p; simpl; rewrite to_Z_0, Zmod_1_r; reflexivity.
+ intros n ih hn.
+ assert (n <= size)%nat as hn' by lia.
+ specialize (ih hn').
+ intros [ p | p | ].
+ 3: {
+ rewrite Zmod_small. reflexivity.
+ split. lia.
+ apply Zpower_gt_1; lia.
+ }
+ - simpl.
+ destruct (bit_add_or (of_pos_rec n p << 1) 1) as (H1, _).
+ rewrite <- H1;clear H1.
+ 2: {
+ intros i; rewrite bit_lsl, bit_1.
+ case eqbP.
+ + intros h; apply to_Z_inj in h; subst. exact (λ e _, diff_false_true e).
+ + exact (λ _ _, diff_false_true).
+ }
+ rewrite add_spec, lsl_spec, ih, to_Z_1; clear ih.
+ rewrite Z.pow_pos_fold, Zpos_P_of_succ_nat.
+ change (Zpos p~1) with (2 ^ 1 * Zpos p + 1)%Z.
+ rewrite Zmod_distr by lia.
+ rewrite Zpower_Zsucc by auto with zarith.
+ rewrite Zplus_mod_idemp_l.
+ rewrite Zmod_small.
+ rewrite Zmult_mod_distr_l; lia.
+ set (a := Z.of_nat n).
+ set (b := Zpos p).
+ change (2 ^ 1) with 2.
+ pose proof (pow2_pos a (Nat2Z.is_nonneg _)).
+ elim_div; intros x y [ ? ha]. lia.
+ destruct ha as [ ha | ]. 2: lia.
+ split. lia.
+ apply Z.lt_le_trans with (2 ^ (a + 1)).
+ 2: apply Z.pow_le_mono_r; subst a; lia.
+ fold (Z.succ a); rewrite Z.pow_succ_r. lia.
+ subst a; lia.
+ - simpl. rewrite lsl_spec, ih, to_Z_1, Zmod_small.
+ rewrite Z.pow_pos_fold, Zpos_P_of_succ_nat, Zpower_Zsucc by lia.
+ change (Zpos p~0) with (2 ^ 1 * Zpos p)%Z.
+ rewrite Z.mul_mod_distr_l; auto with zarith.
+ set (a := Z.of_nat n).
+ set (b := Zpos p).
+ change (2 ^ 1) with 2.
+ pose proof (pow2_pos a (Nat2Z.is_nonneg _)).
+ elim_div; intros x y [ ? ha]. lia.
+ destruct ha as [ ha | ]. 2: lia.
+ split. lia.
+ apply Z.lt_le_trans with (2 ^ (a + 1)).
+ 2: apply Z.pow_le_mono_r; subst a; lia.
+ fold (Z.succ a); rewrite Z.pow_succ_r. lia.
+ subst a; lia.
+Qed.
+
+Lemma is_int n :
+ 0 <= n < 2 ^ φ digits →
+ n = φ (of_Z n).
+Proof.
+ destruct n. reflexivity. 2: lia.
+ intros [_ h]. simpl.
+ unfold of_pos. rewrite of_pos_rec_spec by lia.
+ symmetry; apply Z.mod_small. split. lia. exact h.
+Qed.
+
+Lemma of_Z_spec n : [| of_Z n |] = n mod wB.
+Proof.
+ destruct n. reflexivity.
+ { now simpl; unfold of_pos; rewrite of_pos_rec_spec by lia. }
+ simpl; unfold of_pos; rewrite opp_spec.
+ rewrite of_pos_rec_spec; [ |auto]; fold wB.
+ now rewrite <-(Z.sub_0_l), Zminus_mod_idemp_r.
+Qed.
+
+(* General lemmas *)
+Lemma negbE a b : a = negb b → negb a = b.
+Proof. intros ->; apply negb_involutive. Qed.
+
+Lemma Z_oddE a : Z.odd a = (a mod 2 =? 1)%Z.
+Proof. rewrite Zmod_odd; case Z.odd; reflexivity. Qed.
+
+Lemma Z_evenE a : Z.even a = (a mod 2 =? 0)%Z.
+Proof. rewrite Zmod_even; case Z.even; reflexivity. Qed.
+
+(* is_zero *)
+Lemma is_zeroE n : is_zero n = Z.eqb (φ n) 0.
+Proof.
+ case Z.eqb_spec.
+ - intros h; apply (to_Z_inj n 0) in h; subst n; reflexivity.
+ - generalize (proj1 (is_zero_spec n)).
+ case is_zero; auto; intros ->; auto; destruct 1; reflexivity.
+Qed.
+
+(* bit *)
+Lemma bitE i j : bit i j = Z.testbit φ(i) φ(j).
+Proof.
+ apply negbE; rewrite is_zeroE, lsl_spec, lsr_spec.
+ generalize (φ i) (to_Z_bounded i) (φ j) (to_Z_bounded j); clear i j;
+ intros i [hi hi'] j [hj hj'].
+ rewrite Z.testbit_eqb by auto; rewrite <- Z_oddE, Z.negb_odd, Z_evenE.
+ remember (i / 2 ^ j) as k.
+ change wB with (2 * 2 ^ φ (digits - 1)).
+ unfold Z.modulo at 2.
+ generalize (Z_div_mod_full k 2 (λ k, let 'eq_refl := k in I)); unfold Remainder.
+ destruct Z.div_eucl as [ p q ]; intros [hk [ hq | ]]. 2: lia.
+ rewrite hk.
+ remember φ (digits - 1) as m.
+ replace ((_ + _) * _) with (q * 2 ^ m + p * (2 * 2 ^ m)) by ring.
+ rewrite Z_mod_plus by (subst m; reflexivity).
+ assert (q = 0 ∨ q = 1) as D by lia.
+ destruct D; subst; reflexivity.
+Qed.
+
+(* land, lor, lxor *)
+Lemma lt_pow_lt_log d k n :
+ 0 < d <= n →
+ 0 <= k < 2 ^ d →
+ Z.log2 k < n.
+Proof.
+ intros [hd hdn] [hk hkd].
+ assert (k = 0 ∨ 0 < k) as D by lia.
+ clear hk; destruct D as [ hk | hk ].
+ - subst k; simpl; lia.
+ - apply Z.log2_lt_pow2. lia.
+ eapply Z.lt_le_trans. eassumption.
+ apply Z.pow_le_mono_r; lia.
+Qed.
+
+Lemma land_spec' x y : φ (x land y) = Z.land φ(x) φ(y).
+Proof.
+ apply Z.bits_inj'; intros n hn.
+ destruct (to_Z_bounded (x land y)) as [ hxy hxy' ].
+ destruct (to_Z_bounded x) as [ hx hx' ].
+ destruct (to_Z_bounded y) as [ hy hy' ].
+ case (Z_lt_le_dec n (φ digits)); intros hd.
+ 2: {
+ rewrite !Z.bits_above_log2; auto.
+ - apply Z.land_nonneg; auto.
+ - eapply Z.le_lt_trans.
+ apply Z.log2_land; assumption.
+ apply Z.min_lt_iff.
+ left. apply (lt_pow_lt_log φ digits). exact (conj eq_refl hd).
+ split; assumption.
+ - apply (lt_pow_lt_log φ digits). exact (conj eq_refl hd).
+ split; assumption.
+ }
+ rewrite (is_int n).
+ rewrite Z.land_spec, <- !bitE, land_spec; reflexivity.
+ apply (conj hn).
+ apply (Z.lt_trans _ _ _ hd).
+ apply Zpower2_lt_lin. lia.
+Qed.
+
+Lemma lor_spec' x y : φ (x lor y) = Z.lor φ(x) φ(y).
+Proof.
+ apply Z.bits_inj'; intros n hn.
+ destruct (to_Z_bounded (x lor y)) as [ hxy hxy' ].
+ destruct (to_Z_bounded x) as [ hx hx' ].
+ destruct (to_Z_bounded y) as [ hy hy' ].
+ case (Z_lt_le_dec n (φ digits)); intros hd.
+ 2: {
+ rewrite !Z.bits_above_log2; auto.
+ - apply Z.lor_nonneg; auto.
+ - rewrite Z.log2_lor by assumption.
+ apply Z.max_lub_lt; apply (lt_pow_lt_log φ digits); split; assumption || reflexivity.
+ - apply (lt_pow_lt_log φ digits); split; assumption || reflexivity.
+ }
+ rewrite (is_int n).
+ rewrite Z.lor_spec, <- !bitE, lor_spec; reflexivity.
+ apply (conj hn).
+ apply (Z.lt_trans _ _ _ hd).
+ apply Zpower2_lt_lin. lia.
+Qed.
+
+Lemma lxor_spec' x y : φ (x lxor y) = Z.lxor φ(x) φ(y).
+Proof.
+ apply Z.bits_inj'; intros n hn.
+ destruct (to_Z_bounded (x lxor y)) as [ hxy hxy' ].
+ destruct (to_Z_bounded x) as [ hx hx' ].
+ destruct (to_Z_bounded y) as [ hy hy' ].
+ case (Z_lt_le_dec n (φ digits)); intros hd.
+ 2: {
+ rewrite !Z.bits_above_log2; auto.
+ - apply Z.lxor_nonneg; split; auto.
+ - eapply Z.le_lt_trans.
+ apply Z.log2_lxor; assumption.
+ apply Z.max_lub_lt; apply (lt_pow_lt_log φ digits); split; assumption || reflexivity.
+ - apply (lt_pow_lt_log φ digits); split; assumption || reflexivity.
+ }
+ rewrite (is_int n).
+ rewrite Z.lxor_spec, <- !bitE, lxor_spec; reflexivity.
+ apply (conj hn).
+ apply (Z.lt_trans _ _ _ hd).
+ apply Zpower2_lt_lin. lia.
+Qed.
+
+Lemma landC i j : i land j = j land i.
+Proof.
+ apply bit_ext; intros n.
+ rewrite !land_spec, andb_comm; auto.
+Qed.
+
+Lemma landA i j k : i land (j land k) = i land j land k.
+Proof.
+ apply bit_ext; intros n.
+ rewrite !land_spec, andb_assoc; auto.
+Qed.
+
+Lemma land0 i : 0 land i = 0%int63.
+Proof.
+ apply bit_ext; intros n.
+ rewrite land_spec, bit_0; auto.
+Qed.
+
+Lemma land0_r i : i land 0 = 0%int63.
+Proof. rewrite landC; exact (land0 i). Qed.
+
+Lemma lorC i j : i lor j = j lor i.
+Proof.
+ apply bit_ext; intros n.
+ rewrite !lor_spec, orb_comm; auto.
+Qed.
+
+Lemma lorA i j k : i lor (j lor k) = i lor j lor k.
+Proof.
+ apply bit_ext; intros n.
+ rewrite !lor_spec, orb_assoc; auto.
+Qed.
+
+Lemma lor0 i : 0 lor i = i.
+Proof.
+ apply bit_ext; intros n.
+ rewrite lor_spec, bit_0; auto.
+Qed.
+
+Lemma lor0_r i : i lor 0 = i.
+Proof. rewrite lorC; exact (lor0 i). Qed.
+
+Lemma lxorC i j : i lxor j = j lxor i.
+Proof.
+ apply bit_ext; intros n.
+ rewrite !lxor_spec, xorb_comm; auto.
+Qed.
+
+Lemma lxorA i j k : i lxor (j lxor k) = i lxor j lxor k.
+Proof.
+ apply bit_ext; intros n.
+ rewrite !lxor_spec, xorb_assoc; auto.
+Qed.
+
+Lemma lxor0 i : 0 lxor i = i.
+Proof.
+ apply bit_ext; intros n.
+ rewrite lxor_spec, bit_0, xorb_false_l; auto.
+Qed.
+
+Lemma lxor0_r i : i lxor 0 = i.
+Proof. rewrite lxorC; exact (lxor0 i). Qed.
diff --git a/theories/Numbers/Cyclic/Int63/Ring63.v b/theories/Numbers/Cyclic/Int63/Ring63.v
new file mode 100644
index 0000000000..d230435378
--- /dev/null
+++ b/theories/Numbers/Cyclic/Int63/Ring63.v
@@ -0,0 +1,65 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2018 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(** * Int63 numbers defines Z/(2^63)Z, and can hence be equipped
+ with a ring structure and a ring tactic *)
+
+Require Import Cyclic63 CyclicAxioms.
+
+Local Open Scope int63_scope.
+
+(** Detection of constants *)
+
+Ltac isInt63cst t :=
+ match eval lazy delta [add] in (t + 1)%int63 with
+ | add _ _ => constr:(false)
+ | _ => constr:(true)
+ end.
+
+Ltac Int63cst t :=
+ match eval lazy delta [add] in (t + 1)%int63 with
+ | add _ _ => constr:(NotConstant)
+ | _ => constr:(t)
+ end.
+
+(** The generic ring structure inferred from the Cyclic structure *)
+
+Module Int63ring := CyclicRing Int63Cyclic.
+
+(** Unlike in the generic [CyclicRing], we can use Leibniz here. *)
+
+Lemma Int63_canonic : forall x y, to_Z x = to_Z y -> x = y.
+Proof to_Z_inj.
+
+Lemma ring_theory_switch_eq :
+ forall A (R R':A->A->Prop) zero one add mul sub opp,
+ (forall x y : A, R x y -> R' x y) ->
+ ring_theory zero one add mul sub opp R ->
+ ring_theory zero one add mul sub opp R'.
+Proof.
+intros A R R' zero one add mul sub opp Impl Ring.
+constructor; intros; apply Impl; apply Ring.
+Qed.
+
+Lemma Int63Ring : ring_theory 0 1 add mul sub opp Logic.eq.
+Proof.
+exact (ring_theory_switch_eq _ _ _ _ _ _ _ _ _ Int63_canonic Int63ring.CyclicRing).
+Qed.
+
+Lemma eq31_correct : forall x y, eqb x y = true -> x=y.
+Proof. now apply eqb_spec. Qed.
+
+Add Ring Int63Ring : Int63Ring
+ (decidable eq31_correct,
+ constants [Int63cst]).
+
+Section TestRing.
+Let test : forall x y, 1 + x*y + x*x + 1 = 1*1 + 1 + y*x + 1*x*x.
+intros. ring.
+Qed.
+End TestRing.
diff --git a/theories/Numbers/NatInt/NZAdd.v b/theories/Numbers/NatInt/NZAdd.v
index bc366c508d..9fcb029b3c 100644
--- a/theories/Numbers/NatInt/NZAdd.v
+++ b/theories/Numbers/NatInt/NZAdd.v
@@ -22,14 +22,16 @@ Ltac nzsimpl' := autorewrite with nz nz'.
Theorem add_0_r : forall n, n + 0 == n.
Proof.
-nzinduct n. now nzsimpl.
-intro. nzsimpl. now rewrite succ_inj_wd.
+ nzinduct n.
+ - now nzsimpl.
+ - intro. nzsimpl. now rewrite succ_inj_wd.
Qed.
Theorem add_succ_r : forall n m, n + S m == S (n + m).
Proof.
-intros n m; nzinduct n. now nzsimpl.
-intro. nzsimpl. now rewrite succ_inj_wd.
+ intros n m; nzinduct n.
+ - now nzsimpl.
+ - intro. nzsimpl. now rewrite succ_inj_wd.
Qed.
Theorem add_succ_comm : forall n m, S n + m == n + S m.
@@ -41,8 +43,9 @@ Hint Rewrite add_0_r add_succ_r : nz.
Theorem add_comm : forall n m, n + m == m + n.
Proof.
-intros n m; nzinduct n. now nzsimpl.
-intro. nzsimpl. now rewrite succ_inj_wd.
+ intros n m; nzinduct n.
+ - now nzsimpl.
+ - intro. nzsimpl. now rewrite succ_inj_wd.
Qed.
Theorem add_1_l : forall n, 1 + n == S n.
@@ -59,14 +62,16 @@ Hint Rewrite add_1_l add_1_r : nz.
Theorem add_assoc : forall n m p, n + (m + p) == (n + m) + p.
Proof.
-intros n m p; nzinduct n. now nzsimpl.
-intro. nzsimpl. now rewrite succ_inj_wd.
+ intros n m p; nzinduct n.
+ - now nzsimpl.
+ - intro. nzsimpl. now rewrite succ_inj_wd.
Qed.
Theorem add_cancel_l : forall n m p, p + n == p + m <-> n == m.
Proof.
-intros n m p; nzinduct p. now nzsimpl.
-intro p. nzsimpl. now rewrite succ_inj_wd.
+intros n m p; nzinduct p.
+- now nzsimpl.
+- intro p. nzsimpl. now rewrite succ_inj_wd.
Qed.
Theorem add_cancel_r : forall n m p, n + p == m + p <-> n == m.
diff --git a/theories/Numbers/NatInt/NZAddOrder.v b/theories/Numbers/NatInt/NZAddOrder.v
index 99812ee3fe..5f102e853b 100644
--- a/theories/Numbers/NatInt/NZAddOrder.v
+++ b/theories/Numbers/NatInt/NZAddOrder.v
@@ -17,8 +17,8 @@ Include NZBaseProp NZ <+ NZMulProp NZ <+ NZOrderProp NZ.
Theorem add_lt_mono_l : forall n m p, n < m <-> p + n < p + m.
Proof.
-intros n m p; nzinduct p. now nzsimpl.
-intro p. nzsimpl. now rewrite <- succ_lt_mono.
+ intros n m p; nzinduct p. - now nzsimpl.
+ - intro p. nzsimpl. now rewrite <- succ_lt_mono.
Qed.
Theorem add_lt_mono_r : forall n m p, n < m <-> n + p < m + p.
@@ -35,8 +35,8 @@ Qed.
Theorem add_le_mono_l : forall n m p, n <= m <-> p + n <= p + m.
Proof.
-intros n m p; nzinduct p. now nzsimpl.
-intro p. nzsimpl. now rewrite <- succ_le_mono.
+ intros n m p; nzinduct p. - now nzsimpl.
+ - intro p. nzsimpl. now rewrite <- succ_le_mono.
Qed.
Theorem add_le_mono_r : forall n m p, n <= m <-> n + p <= m + p.
@@ -124,9 +124,9 @@ Qed.
Theorem add_le_cases : forall n m p q, n + m <= p + q -> n <= p \/ m <= q.
Proof.
intros n m p q H.
-destruct (le_gt_cases n p) as [H1 | H1]. now left.
-destruct (le_gt_cases m q) as [H2 | H2]. now right.
-contradict H; rewrite nle_gt. now apply add_lt_mono.
+destruct (le_gt_cases n p) as [H1 | H1]. - now left.
+- destruct (le_gt_cases m q) as [H2 | H2]. + now right.
+ + contradict H; rewrite nle_gt. now apply add_lt_mono.
Qed.
Theorem add_neg_cases : forall n m, n + m < 0 -> n < 0 \/ m < 0.
@@ -156,10 +156,10 @@ Qed.
Lemma le_exists_sub : forall n m, n<=m -> exists p, m == p+n /\ 0<=p.
Proof.
- intros n m H. apply le_ind with (4:=H). solve_proper.
- exists 0; nzsimpl; split; order.
- clear m H. intros m H (p & EQ & LE). exists (S p).
- split. nzsimpl. now f_equiv. now apply le_le_succ_r.
+ intros n m H. apply le_ind with (4:=H). - solve_proper.
+ - exists 0; nzsimpl; split; order.
+ - clear m H. intros m H (p & EQ & LE). exists (S p).
+ split. + nzsimpl. now f_equiv. + now apply le_le_succ_r.
Qed.
(** For the moment, it doesn't seem possible to relate
diff --git a/theories/Numbers/NatInt/NZBase.v b/theories/Numbers/NatInt/NZBase.v
index 595b2182ab..840a798d9b 100644
--- a/theories/Numbers/NatInt/NZBase.v
+++ b/theories/Numbers/NatInt/NZBase.v
@@ -49,8 +49,8 @@ bidirectional induction steps *)
Theorem succ_inj_wd : forall n1 n2, S n1 == S n2 <-> n1 == n2.
Proof.
intros; split.
-apply succ_inj.
-intros. now f_equiv.
+- apply succ_inj.
+- intros. now f_equiv.
Qed.
Theorem succ_inj_wd_neg : forall n m, S n ~= S m <-> n ~= m.
@@ -72,9 +72,9 @@ Theorem central_induction :
forall n, A n.
Proof.
intros z Base Step; revert Base; pattern z; apply bi_induction.
-solve_proper.
-intro; now apply bi_induction.
-intro; pose proof (Step n); tauto.
+- solve_proper.
+- intro; now apply bi_induction.
+- intro; pose proof (Step n); tauto.
Qed.
End CentralInduction.
diff --git a/theories/Numbers/NatInt/NZDiv.v b/theories/Numbers/NatInt/NZDiv.v
index 550aa226ac..b94cef7cee 100644
--- a/theories/Numbers/NatInt/NZDiv.v
+++ b/theories/Numbers/NatInt/NZDiv.v
@@ -54,22 +54,22 @@ Proof.
intros b.
assert (U : forall q1 q2 r1 r2,
b*q1+r1 == b*q2+r2 -> 0<=r1<b -> 0<=r2 -> q1<q2 -> False).
- intros q1 q2 r1 r2 EQ LT Hr1 Hr2.
- contradict EQ.
- apply lt_neq.
- apply lt_le_trans with (b*q1+b).
- rewrite <- add_lt_mono_l. tauto.
- apply le_trans with (b*q2).
- rewrite mul_comm, <- mul_succ_l, mul_comm.
- apply mul_le_mono_nonneg_l; intuition; try order.
- rewrite le_succ_l; auto.
- rewrite <- (add_0_r (b*q2)) at 1.
- rewrite <- add_le_mono_l. tauto.
-
-intros q1 q2 r1 r2 Hr1 Hr2 EQ; destruct (lt_trichotomy q1 q2) as [LT|[EQ'|GT]].
-elim (U q1 q2 r1 r2); intuition.
-split; auto. rewrite EQ' in EQ. rewrite add_cancel_l in EQ; auto.
-elim (U q2 q1 r2 r1); intuition.
+- intros q1 q2 r1 r2 EQ LT Hr1 Hr2.
+ contradict EQ.
+ apply lt_neq.
+ apply lt_le_trans with (b*q1+b).
+ + rewrite <- add_lt_mono_l. tauto.
+ + apply le_trans with (b*q2).
+ * rewrite mul_comm, <- mul_succ_l, mul_comm.
+ apply mul_le_mono_nonneg_l; intuition; try order.
+ rewrite le_succ_l; auto.
+ * rewrite <- (add_0_r (b*q2)) at 1.
+ rewrite <- add_le_mono_l. tauto.
+
+- intros q1 q2 r1 r2 Hr1 Hr2 EQ; destruct (lt_trichotomy q1 q2) as [LT|[EQ'|GT]].
+ + elim (U q1 q2 r1 r2); intuition.
+ + split; auto. rewrite EQ' in EQ. rewrite add_cancel_l in EQ; auto.
+ + elim (U q2 q1 r2 r1); intuition.
Qed.
Theorem div_unique:
@@ -78,8 +78,8 @@ Theorem div_unique:
Proof.
intros a b q r Ha (Hb,Hr) EQ.
destruct (div_mod_unique b q (a/b) r (a mod b)); auto.
-apply mod_bound_pos; order.
-rewrite <- div_mod; order.
+- apply mod_bound_pos; order.
+- rewrite <- div_mod; order.
Qed.
Theorem mod_unique:
@@ -88,8 +88,8 @@ Theorem mod_unique:
Proof.
intros a b q r Ha (Hb,Hr) EQ.
destruct (div_mod_unique b q (a/b) r (a mod b)); auto.
-apply mod_bound_pos; order.
-rewrite <- div_mod; order.
+- apply mod_bound_pos; order.
+- rewrite <- div_mod; order.
Qed.
Theorem div_unique_exact a b q:
@@ -167,16 +167,16 @@ Qed.
Lemma div_mul : forall a b, 0<=a -> 0<b -> (a*b)/b == a.
Proof.
intros; symmetry. apply div_unique_exact; trivial.
-apply mul_nonneg_nonneg; order.
-apply mul_comm.
+- apply mul_nonneg_nonneg; order.
+- apply mul_comm.
Qed.
Lemma mod_mul : forall a b, 0<=a -> 0<b -> (a*b) mod b == 0.
Proof.
intros; symmetry.
apply mod_unique with a; try split; try order.
-apply mul_nonneg_nonneg; order.
-nzsimpl; apply mul_comm.
+- apply mul_nonneg_nonneg; order.
+- nzsimpl; apply mul_comm.
Qed.
@@ -187,10 +187,10 @@ Qed.
Theorem mod_le: forall a b, 0<=a -> 0<b -> a mod b <= a.
Proof.
intros. destruct (le_gt_cases b a).
-apply le_trans with b; auto.
-apply lt_le_incl. destruct (mod_bound_pos a b); auto.
-rewrite lt_eq_cases; right.
-apply mod_small; auto.
+- apply le_trans with b; auto.
+ apply lt_le_incl. destruct (mod_bound_pos a b); auto.
+- rewrite lt_eq_cases; right.
+ apply mod_small; auto.
Qed.
@@ -219,9 +219,9 @@ Qed.
Lemma div_small_iff : forall a b, 0<=a -> 0<b -> (a/b==0 <-> a<b).
Proof.
intros a b Ha Hb; split; intros Hab.
-destruct (lt_ge_cases a b); auto.
-symmetry in Hab. contradict Hab. apply lt_neq, div_str_pos; auto.
-apply div_small; auto.
+- destruct (lt_ge_cases a b); auto.
+ symmetry in Hab. contradict Hab. apply lt_neq, div_str_pos; auto.
+- apply div_small; auto.
Qed.
Lemma mod_small_iff : forall a b, 0<=a -> 0<b -> (a mod b == a <-> a<b).
@@ -236,9 +236,9 @@ Qed.
Lemma div_str_pos_iff : forall a b, 0<=a -> 0<b -> (0<a/b <-> b<=a).
Proof.
intros a b Ha Hb; split; intros Hab.
-destruct (lt_ge_cases a b) as [LT|LE]; auto.
-rewrite <- div_small_iff in LT; order.
-apply div_str_pos; auto.
+- destruct (lt_ge_cases a b) as [LT|LE]; auto.
+ rewrite <- div_small_iff in LT; order.
+- apply div_str_pos; auto.
Qed.
@@ -250,14 +250,14 @@ Proof.
intros.
assert (0 < b) by (apply lt_trans with 1; auto using lt_0_1).
destruct (lt_ge_cases a b).
-rewrite div_small; try split; order.
-rewrite (div_mod a b) at 2 by order.
-apply lt_le_trans with (b*(a/b)).
-rewrite <- (mul_1_l (a/b)) at 1.
-rewrite <- mul_lt_mono_pos_r; auto.
-apply div_str_pos; auto.
-rewrite <- (add_0_r (b*(a/b))) at 1.
-rewrite <- add_le_mono_l. destruct (mod_bound_pos a b); order.
+- rewrite div_small; try split; order.
+- rewrite (div_mod a b) at 2 by order.
+ apply lt_le_trans with (b*(a/b)).
+ + rewrite <- (mul_1_l (a/b)) at 1.
+ rewrite <- mul_lt_mono_pos_r; auto.
+ apply div_str_pos; auto.
+ + rewrite <- (add_0_r (b*(a/b))) at 1.
+ rewrite <- add_le_mono_l. destruct (mod_bound_pos a b); order.
Qed.
(** [le] is compatible with a positive division. *)
@@ -276,8 +276,8 @@ apply lt_le_trans with b; auto.
rewrite (div_mod b c) at 1 by order.
rewrite <- add_assoc, <- add_le_mono_l.
apply le_trans with (c+0).
-nzsimpl; destruct (mod_bound_pos b c); order.
-rewrite <- add_le_mono_l. destruct (mod_bound_pos a c); order.
+- nzsimpl; destruct (mod_bound_pos b c); order.
+- rewrite <- add_le_mono_l. destruct (mod_bound_pos a c); order.
Qed.
(** The following two properties could be used as specification of div *)
@@ -334,11 +334,11 @@ Theorem div_le_lower_bound:
Proof.
intros a b q Ha Hb H.
destruct (lt_ge_cases 0 q).
-rewrite <- (div_mul q b); try order.
-apply div_le_mono; auto.
-rewrite mul_comm; split; auto.
-apply lt_le_incl, mul_pos_pos; auto.
-apply le_trans with 0; auto; apply div_pos; auto.
+- rewrite <- (div_mul q b); try order.
+ apply div_le_mono; auto.
+ rewrite mul_comm; split; auto.
+ apply lt_le_incl, mul_pos_pos; auto.
+- apply le_trans with 0; auto; apply div_pos; auto.
Qed.
(** A division respects opposite monotonicity for the divisor *)
@@ -350,10 +350,10 @@ Proof.
apply div_le_lower_bound; auto.
rewrite (div_mod p r) at 2 by order.
apply le_trans with (r*(p/r)).
- apply mul_le_mono_nonneg_r; try order.
- apply div_pos; order.
- rewrite <- (add_0_r (r*(p/r))) at 1.
- rewrite <- add_le_mono_l. destruct (mod_bound_pos p r); order.
+ - apply mul_le_mono_nonneg_r; try order.
+ apply div_pos; order.
+ - rewrite <- (add_0_r (r*(p/r))) at 1.
+ rewrite <- add_le_mono_l. destruct (mod_bound_pos p r); order.
Qed.
@@ -365,9 +365,9 @@ Proof.
intros.
symmetry.
apply mod_unique with (a/c+b); auto.
- apply mod_bound_pos; auto.
- rewrite mul_add_distr_l, add_shuffle0, <- div_mod by order.
- now rewrite mul_comm.
+ - apply mod_bound_pos; auto.
+ - rewrite mul_add_distr_l, add_shuffle0, <- div_mod by order.
+ now rewrite mul_comm.
Qed.
Lemma div_add : forall a b c, 0<=a -> 0<=a+b*c -> 0<c ->
@@ -396,14 +396,14 @@ Proof.
intros.
symmetry.
apply div_unique with ((a mod b)*c).
- apply mul_nonneg_nonneg; order.
- split.
- apply mul_nonneg_nonneg; destruct (mod_bound_pos a b); order.
- rewrite <- mul_lt_mono_pos_r; auto. destruct (mod_bound_pos a b); auto.
- rewrite (div_mod a b) at 1 by order.
- rewrite mul_add_distr_r.
- rewrite add_cancel_r.
- rewrite <- 2 mul_assoc. now rewrite (mul_comm c).
+ - apply mul_nonneg_nonneg; order.
+ - split.
+ + apply mul_nonneg_nonneg; destruct (mod_bound_pos a b); order.
+ + rewrite <- mul_lt_mono_pos_r; auto. destruct (mod_bound_pos a b); auto.
+ - rewrite (div_mod a b) at 1 by order.
+ rewrite mul_add_distr_r.
+ rewrite add_cancel_r.
+ rewrite <- 2 mul_assoc. now rewrite (mul_comm c).
Qed.
Lemma div_mul_cancel_l : forall a b c, 0<=a -> 0<b -> 0<c ->
@@ -418,10 +418,10 @@ Proof.
intros.
rewrite <- (add_cancel_l _ _ ((c*b)* ((c*a)/(c*b)))).
rewrite <- div_mod.
- rewrite div_mul_cancel_l; auto.
- rewrite <- mul_assoc, <- mul_add_distr_l, mul_cancel_l by order.
- apply div_mod; order.
- rewrite <- neq_mul_0; intuition; order.
+ - rewrite div_mul_cancel_l; auto.
+ rewrite <- mul_assoc, <- mul_add_distr_l, mul_cancel_l by order.
+ apply div_mod; order.
+ - rewrite <- neq_mul_0; intuition; order.
Qed.
Lemma mul_mod_distr_r: forall a b c, 0<=a -> 0<b -> 0<c ->
@@ -447,8 +447,8 @@ Proof.
rewrite add_comm, (mul_comm n), (mul_comm _ b).
rewrite mul_add_distr_l, mul_assoc.
intros. rewrite mod_add; auto.
- now rewrite mul_comm.
- apply mul_nonneg_nonneg; destruct (mod_bound_pos a n); auto.
+ - now rewrite mul_comm.
+ - apply mul_nonneg_nonneg; destruct (mod_bound_pos a n); auto.
Qed.
Lemma mul_mod_idemp_r : forall a b n, 0<=a -> 0<=b -> 0<n ->
@@ -460,8 +460,8 @@ Qed.
Theorem mul_mod: forall a b n, 0<=a -> 0<=b -> 0<n ->
(a * b) mod n == ((a mod n) * (b mod n)) mod n.
Proof.
- intros. rewrite mul_mod_idemp_l, mul_mod_idemp_r; trivial. reflexivity.
- now destruct (mod_bound_pos b n).
+ intros. rewrite mul_mod_idemp_l, mul_mod_idemp_r; trivial. - reflexivity.
+ - now destruct (mod_bound_pos b n).
Qed.
Lemma add_mod_idemp_l : forall a b n, 0<=a -> 0<=b -> 0<n ->
@@ -471,8 +471,8 @@ Proof.
generalize (add_nonneg_nonneg _ _ Ha Hb).
rewrite (div_mod a n) at 1 2 by order.
rewrite <- add_assoc, add_comm, mul_comm.
- intros. rewrite mod_add; trivial. reflexivity.
- apply add_nonneg_nonneg; auto. destruct (mod_bound_pos a n); auto.
+ intros. rewrite mod_add; trivial. - reflexivity.
+ - apply add_nonneg_nonneg; auto. destruct (mod_bound_pos a n); auto.
Qed.
Lemma add_mod_idemp_r : forall a b n, 0<=a -> 0<=b -> 0<n ->
@@ -484,8 +484,8 @@ Qed.
Theorem add_mod: forall a b n, 0<=a -> 0<=b -> 0<n ->
(a+b) mod n == (a mod n + b mod n) mod n.
Proof.
- intros. rewrite add_mod_idemp_l, add_mod_idemp_r; trivial. reflexivity.
- now destruct (mod_bound_pos b n).
+ intros. rewrite add_mod_idemp_l, add_mod_idemp_r; trivial. - reflexivity.
+ - now destruct (mod_bound_pos b n).
Qed.
Lemma div_div : forall a b c, 0<=a -> 0<b -> 0<c ->
@@ -494,18 +494,18 @@ Proof.
intros a b c Ha Hb Hc.
apply div_unique with (b*((a/b) mod c) + a mod b); trivial.
(* begin 0<= ... <b*c *)
- destruct (mod_bound_pos (a/b) c), (mod_bound_pos a b); auto using div_pos.
- split.
- apply add_nonneg_nonneg; auto.
- apply mul_nonneg_nonneg; order.
- apply lt_le_trans with (b*((a/b) mod c) + b).
- rewrite <- add_lt_mono_l; auto.
- rewrite <- mul_succ_r, <- mul_le_mono_pos_l, le_succ_l; auto.
- (* end 0<= ... < b*c *)
- rewrite (div_mod a b) at 1 by order.
- rewrite add_assoc, add_cancel_r.
- rewrite <- mul_assoc, <- mul_add_distr_l, mul_cancel_l by order.
- apply div_mod; order.
+ - destruct (mod_bound_pos (a/b) c), (mod_bound_pos a b); auto using div_pos.
+ split.
+ + apply add_nonneg_nonneg; auto.
+ apply mul_nonneg_nonneg; order.
+ + apply lt_le_trans with (b*((a/b) mod c) + b).
+ * rewrite <- add_lt_mono_l; auto.
+ * rewrite <- mul_succ_r, <- mul_le_mono_pos_l, le_succ_l; auto.
+ (* end 0<= ... < b*c *)
+ - rewrite (div_mod a b) at 1 by order.
+ rewrite add_assoc, add_cancel_r.
+ rewrite <- mul_assoc, <- mul_add_distr_l, mul_cancel_l by order.
+ apply div_mod; order.
Qed.
Lemma mod_mul_r : forall a b c, 0<=a -> 0<b -> 0<c ->
@@ -527,10 +527,10 @@ Theorem div_mul_le:
Proof.
intros.
apply div_le_lower_bound; auto.
- apply mul_nonneg_nonneg; auto.
- rewrite mul_assoc, (mul_comm b c), <- mul_assoc.
- apply mul_le_mono_nonneg_l; auto.
- apply mul_div_le; auto.
+ - apply mul_nonneg_nonneg; auto.
+ - rewrite mul_assoc, (mul_comm b c), <- mul_assoc.
+ apply mul_le_mono_nonneg_l; auto.
+ apply mul_div_le; auto.
Qed.
(** mod is related to divisibility *)
@@ -539,9 +539,9 @@ Lemma mod_divides : forall a b, 0<=a -> 0<b ->
(a mod b == 0 <-> exists c, a == b*c).
Proof.
split.
- intros. exists (a/b). rewrite div_exact; auto.
- intros (c,Hc). rewrite Hc, mul_comm. apply mod_mul; auto.
- rewrite (mul_le_mono_pos_l _ _ b); auto. nzsimpl. order.
+ - intros. exists (a/b). rewrite div_exact; auto.
+ - intros (c,Hc). rewrite Hc, mul_comm. apply mod_mul; auto.
+ rewrite (mul_le_mono_pos_l _ _ b); auto. nzsimpl. order.
Qed.
End NZDivProp.
diff --git a/theories/Numbers/NatInt/NZGcd.v b/theories/Numbers/NatInt/NZGcd.v
index c38d1aac31..1ac89ce942 100644
--- a/theories/Numbers/NatInt/NZGcd.v
+++ b/theories/Numbers/NatInt/NZGcd.v
@@ -72,15 +72,15 @@ Lemma eq_mul_1_nonneg : forall n m,
Proof.
intros n m Hn H.
le_elim Hn.
- destruct (lt_ge_cases m 0) as [Hm|Hm].
- generalize (mul_pos_neg n m Hn Hm). order'.
- le_elim Hm.
- apply le_succ_l in Hn. rewrite <- one_succ in Hn.
- le_elim Hn.
- generalize (lt_1_mul_pos n m Hn Hm). order.
- rewrite <- Hn, mul_1_l in H. now split.
- rewrite <- Hm, mul_0_r in H. order'.
- rewrite <- Hn, mul_0_l in H. order'.
+ - destruct (lt_ge_cases m 0) as [Hm|Hm].
+ + generalize (mul_pos_neg n m Hn Hm). order'.
+ + le_elim Hm.
+ * apply le_succ_l in Hn. rewrite <- one_succ in Hn.
+ le_elim Hn.
+ -- generalize (lt_1_mul_pos n m Hn Hm). order.
+ -- rewrite <- Hn, mul_1_l in H. now split.
+ * rewrite <- Hm, mul_0_r in H. order'.
+ - rewrite <- Hn, mul_0_l in H. order'.
Qed.
Lemma eq_mul_1_nonneg' : forall n m,
@@ -117,13 +117,13 @@ Lemma divide_antisym_nonneg : forall n m,
Proof.
intros n m Hn Hm (q,Hq) (r,Hr).
le_elim Hn.
- destruct (lt_ge_cases q 0) as [Hq'|Hq'].
- generalize (mul_neg_pos q n Hq' Hn). order.
- rewrite Hq, mul_assoc in Hr. symmetry in Hr.
- apply mul_id_l in Hr; [|order].
- destruct (eq_mul_1_nonneg' r q) as [_ H]; trivial.
- now rewrite H, mul_1_l in Hq.
- rewrite <- Hn, mul_0_r in Hq. now rewrite <- Hn.
+ - destruct (lt_ge_cases q 0) as [Hq'|Hq'].
+ + generalize (mul_neg_pos q n Hq' Hn). order.
+ + rewrite Hq, mul_assoc in Hr. symmetry in Hr.
+ apply mul_id_l in Hr; [|order].
+ destruct (eq_mul_1_nonneg' r q) as [_ H]; trivial.
+ now rewrite H, mul_1_l in Hq.
+ - rewrite <- Hn, mul_0_r in Hq. now rewrite <- Hn.
Qed.
Lemma mul_divide_mono_l : forall n m p, (n | m) -> (p * n | p * m).
@@ -140,8 +140,8 @@ Lemma mul_divide_cancel_l : forall n m p, p ~= 0 ->
((p * n | p * m) <-> (n | m)).
Proof.
intros n m p Hp. split.
- intros (q,Hq). exists q. now rewrite mul_shuffle3, mul_cancel_l in Hq.
- apply mul_divide_mono_l.
+ - intros (q,Hq). exists q. now rewrite mul_shuffle3, mul_cancel_l in Hq.
+ - apply mul_divide_mono_l.
Qed.
Lemma mul_divide_cancel_r : forall n m p, p ~= 0 ->
@@ -179,14 +179,14 @@ Qed.
Lemma divide_pos_le : forall n m, 0 < m -> (n | m) -> n <= m.
Proof.
intros n m Hm (q,Hq).
- destruct (le_gt_cases n 0) as [Hn|Hn]. order.
- rewrite Hq.
- destruct (lt_ge_cases q 0) as [Hq'|Hq'].
- generalize (mul_neg_pos q n Hq' Hn). order.
- le_elim Hq'.
- rewrite <- (mul_1_l n) at 1. apply mul_le_mono_pos_r; trivial.
- now rewrite one_succ, le_succ_l.
- rewrite <- Hq', mul_0_l in Hq. order.
+ destruct (le_gt_cases n 0) as [Hn|Hn]. - order.
+ - rewrite Hq.
+ destruct (lt_ge_cases q 0) as [Hq'|Hq'].
+ + generalize (mul_neg_pos q n Hq' Hn). order.
+ + le_elim Hq'.
+ * rewrite <- (mul_1_l n) at 1. apply mul_le_mono_pos_r; trivial.
+ now rewrite one_succ, le_succ_l.
+ * rewrite <- Hq', mul_0_l in Hq. order.
Qed.
(** Basic properties of gcd *)
@@ -197,28 +197,28 @@ Lemma gcd_unique : forall n m p,
gcd n m == p.
Proof.
intros n m p Hp Hn Hm H.
- apply divide_antisym_nonneg; trivial. apply gcd_nonneg.
- apply H. apply gcd_divide_l. apply gcd_divide_r.
- now apply gcd_greatest.
+ apply divide_antisym_nonneg; trivial. - apply gcd_nonneg.
+ - apply H. + apply gcd_divide_l. + apply gcd_divide_r.
+ - now apply gcd_greatest.
Qed.
Instance gcd_wd : Proper (eq==>eq==>eq) gcd.
Proof.
intros x x' Hx y y' Hy.
apply gcd_unique.
- apply gcd_nonneg.
- rewrite Hx. apply gcd_divide_l.
- rewrite Hy. apply gcd_divide_r.
- intro. rewrite Hx, Hy. apply gcd_greatest.
+ - apply gcd_nonneg.
+ - rewrite Hx. apply gcd_divide_l.
+ - rewrite Hy. apply gcd_divide_r.
+ - intro. rewrite Hx, Hy. apply gcd_greatest.
Qed.
Lemma gcd_divide_iff : forall n m p,
(p | gcd n m) <-> (p | n) /\ (p | m).
Proof.
- intros. split. split.
- transitivity (gcd n m); trivial using gcd_divide_l.
- transitivity (gcd n m); trivial using gcd_divide_r.
- intros (H,H'). now apply gcd_greatest.
+ intros. split. - split.
+ + transitivity (gcd n m); trivial using gcd_divide_l.
+ + transitivity (gcd n m); trivial using gcd_divide_r.
+ - intros (H,H'). now apply gcd_greatest.
Qed.
Lemma gcd_unique_alt : forall n m p, 0<=p ->
@@ -227,9 +227,9 @@ Lemma gcd_unique_alt : forall n m p, 0<=p ->
Proof.
intros n m p Hp H.
apply gcd_unique; trivial.
- apply H. apply divide_refl.
- apply H. apply divide_refl.
- intros. apply H. now split.
+ - apply H. apply divide_refl.
+ - apply H. apply divide_refl.
+ - intros. apply H. now split.
Qed.
Lemma gcd_comm : forall n m, gcd n m == gcd m n.
@@ -247,8 +247,8 @@ Qed.
Lemma gcd_0_l_nonneg : forall n, 0<=n -> gcd 0 n == n.
Proof.
intros. apply gcd_unique; trivial.
- apply divide_0_r.
- apply divide_refl.
+ - apply divide_0_r.
+ - apply divide_refl.
Qed.
Lemma gcd_0_r_nonneg : forall n, 0<=n -> gcd n 0 == n.
@@ -284,24 +284,26 @@ Qed.
Lemma gcd_eq_0 : forall n m, gcd n m == 0 <-> n == 0 /\ m == 0.
Proof.
- intros. split. split.
- now apply gcd_eq_0_l with m.
- now apply gcd_eq_0_r with n.
- intros (EQ,EQ'). rewrite EQ, EQ'. now apply gcd_0_r_nonneg.
+ intros. split.
+ - split.
+ + now apply gcd_eq_0_l with m.
+ + now apply gcd_eq_0_r with n.
+ - intros (EQ,EQ'). rewrite EQ, EQ'. now apply gcd_0_r_nonneg.
Qed.
Lemma gcd_mul_diag_l : forall n m, 0<=n -> gcd n (n*m) == n.
Proof.
intros n m Hn. apply gcd_unique_alt; trivial.
- intros q. split. split; trivial. now apply divide_mul_l.
- now destruct 1.
+ intros q. split. - split; trivial. now apply divide_mul_l.
+ - now destruct 1.
Qed.
Lemma divide_gcd_iff : forall n m, 0<=n -> ((n|m) <-> gcd n m == n).
Proof.
- intros n m Hn. split. intros (q,Hq). rewrite Hq.
- rewrite mul_comm. now apply gcd_mul_diag_l.
- intros EQ. rewrite <- EQ. apply gcd_divide_r.
+ intros n m Hn. split.
+ - intros (q,Hq). rewrite Hq.
+ rewrite mul_comm. now apply gcd_mul_diag_l.
+ - intros EQ. rewrite <- EQ. apply gcd_divide_r.
Qed.
End NZGcdProp.
diff --git a/theories/Numbers/NatInt/NZLog.v b/theories/Numbers/NatInt/NZLog.v
index 794851a9dd..1951cfc3ef 100644
--- a/theories/Numbers/NatInt/NZLog.v
+++ b/theories/Numbers/NatInt/NZLog.v
@@ -40,10 +40,10 @@ Module Type NZLog2Prop
Lemma log2_nonneg : forall a, 0 <= log2 a.
Proof.
intros a. destruct (le_gt_cases a 0) as [Ha|Ha].
- now rewrite log2_nonpos.
- destruct (log2_spec a Ha) as (_,LT).
- apply lt_succ_r, (pow_gt_1 2). order'.
- rewrite <- le_succ_l, <- one_succ in Ha. order.
+ - now rewrite log2_nonpos.
+ - destruct (log2_spec a Ha) as (_,LT).
+ apply lt_succ_r, (pow_gt_1 2). + order'.
+ + rewrite <- le_succ_l, <- one_succ in Ha. order.
Qed.
(** A tactic for proving positivity and non-negativity *)
@@ -62,17 +62,17 @@ Lemma log2_unique : forall a b, 0<=b -> 2^b<=a<2^(S b) -> log2 a == b.
Proof.
intros a b Hb (LEb,LTb).
assert (Ha : 0 < a).
- apply lt_le_trans with (2^b); trivial.
- apply pow_pos_nonneg; order'.
- assert (Hc := log2_nonneg a).
- destruct (log2_spec a Ha) as (LEc,LTc).
- assert (log2 a <= b).
- apply lt_succ_r, (pow_lt_mono_r_iff 2); try order'.
- now apply le_le_succ_r.
- assert (b <= log2 a).
- apply lt_succ_r, (pow_lt_mono_r_iff 2); try order'.
- now apply le_le_succ_r.
- order.
+ - apply lt_le_trans with (2^b); trivial.
+ apply pow_pos_nonneg; order'.
+ - assert (Hc := log2_nonneg a).
+ destruct (log2_spec a Ha) as (LEc,LTc).
+ assert (log2 a <= b).
+ + apply lt_succ_r, (pow_lt_mono_r_iff 2); try order'.
+ now apply le_le_succ_r.
+ + assert (b <= log2 a).
+ * apply lt_succ_r, (pow_lt_mono_r_iff 2); try order'.
+ now apply le_le_succ_r.
+ * order.
Qed.
(** Hence log2 is a morphism. *)
@@ -81,9 +81,9 @@ Instance log2_wd : Proper (eq==>eq) log2.
Proof.
intros x x' Hx.
destruct (le_gt_cases x 0).
- rewrite 2 log2_nonpos; trivial. reflexivity. now rewrite <- Hx.
- apply log2_unique. apply log2_nonneg.
- rewrite Hx in *. now apply log2_spec.
+ - rewrite 2 log2_nonpos; trivial. + reflexivity. + now rewrite <- Hx.
+ - apply log2_unique. + apply log2_nonneg.
+ + rewrite Hx in *. now apply log2_spec.
Qed.
(** An alternate specification *)
@@ -95,24 +95,24 @@ Proof.
destruct (log2_spec _ Ha) as (LE,LT).
destruct (le_exists_sub _ _ LE) as (r & Hr & Hr').
exists r.
- split. now rewrite add_comm.
- split. trivial.
- apply (add_lt_mono_r _ _ (2^log2 a)).
- rewrite <- Hr. generalize LT.
- rewrite pow_succ_r by order_pos.
- rewrite two_succ at 1. now nzsimpl.
+ split. - now rewrite add_comm.
+ - split. + trivial.
+ + apply (add_lt_mono_r _ _ (2^log2 a)).
+ rewrite <- Hr. generalize LT.
+ rewrite pow_succ_r by order_pos.
+ rewrite two_succ at 1. now nzsimpl.
Qed.
Lemma log2_unique' : forall a b c, 0<=b -> 0<=c<2^b ->
a == 2^b + c -> log2 a == b.
Proof.
intros a b c Hb (Hc,H) EQ.
- apply log2_unique. trivial.
- rewrite EQ.
- split.
- rewrite <- add_0_r at 1. now apply add_le_mono_l.
- rewrite pow_succ_r by order.
- rewrite two_succ at 2. nzsimpl. now apply add_lt_mono_l.
+ apply log2_unique. - trivial.
+ - rewrite EQ.
+ split.
+ + rewrite <- add_0_r at 1. now apply add_le_mono_l.
+ + rewrite pow_succ_r by order.
+ rewrite two_succ at 2. nzsimpl. now apply add_lt_mono_l.
Qed.
(** log2 is exact on powers of 2 *)
@@ -121,7 +121,7 @@ Lemma log2_pow2 : forall a, 0<=a -> log2 (2^a) == a.
Proof.
intros a Ha.
apply log2_unique' with 0; trivial.
- split; order_pos. now nzsimpl.
+ - split; order_pos. - now nzsimpl.
Qed.
(** log2 and predecessors of powers of 2 *)
@@ -131,12 +131,12 @@ Proof.
intros a Ha.
assert (Ha' : S (P a) == a) by (now rewrite lt_succ_pred with 0).
apply log2_unique.
- apply lt_succ_r; order.
- rewrite <-le_succ_l, <-lt_succ_r, Ha'.
- rewrite lt_succ_pred with 0.
- split; try easy. apply pow_lt_mono_r_iff; try order'.
- rewrite succ_lt_mono, Ha'. apply lt_succ_diag_r.
- apply pow_pos_nonneg; order'.
+ - apply lt_succ_r; order.
+ - rewrite <-le_succ_l, <-lt_succ_r, Ha'.
+ rewrite lt_succ_pred with 0.
+ + split; try easy. apply pow_lt_mono_r_iff; try order'.
+ rewrite succ_lt_mono, Ha'. apply lt_succ_diag_r.
+ + apply pow_pos_nonneg; order'.
Qed.
(** log2 and basic constants *)
@@ -167,11 +167,11 @@ Qed.
Lemma log2_null : forall a, log2 a == 0 <-> a <= 1.
Proof.
intros a. split; intros H.
- destruct (le_gt_cases a 1) as [Ha|Ha]; trivial.
- generalize (log2_pos a Ha); order.
- le_elim H.
- apply log2_nonpos. apply lt_succ_r. now rewrite <- one_succ.
- rewrite H. apply log2_1.
+ - destruct (le_gt_cases a 1) as [Ha|Ha]; trivial.
+ generalize (log2_pos a Ha); order.
+ - le_elim H.
+ + apply log2_nonpos. apply lt_succ_r. now rewrite <- one_succ.
+ + rewrite H. apply log2_1.
Qed.
(** log2 is a monotone function (but not a strict one) *)
@@ -180,11 +180,11 @@ Lemma log2_le_mono : forall a b, a<=b -> log2 a <= log2 b.
Proof.
intros a b H.
destruct (le_gt_cases a 0) as [Ha|Ha].
- rewrite log2_nonpos; order_pos.
- assert (Hb : 0 < b) by order.
- destruct (log2_spec a Ha) as (LEa,_).
- destruct (log2_spec b Hb) as (_,LTb).
- apply lt_succ_r, (pow_lt_mono_r_iff 2); order_pos.
+ - rewrite log2_nonpos; order_pos.
+ - assert (Hb : 0 < b) by order.
+ destruct (log2_spec a Ha) as (LEa,_).
+ destruct (log2_spec b Hb) as (_,LTb).
+ apply lt_succ_r, (pow_lt_mono_r_iff 2); order_pos.
Qed.
(** No reverse result for <=, consider for instance log2 3 <= log2 2 *)
@@ -193,13 +193,13 @@ Lemma log2_lt_cancel : forall a b, log2 a < log2 b -> a < b.
Proof.
intros a b H.
destruct (le_gt_cases b 0) as [Hb|Hb].
- rewrite (log2_nonpos b) in H; trivial.
- generalize (log2_nonneg a); order.
- destruct (le_gt_cases a 0) as [Ha|Ha]. order.
- destruct (log2_spec a Ha) as (_,LTa).
- destruct (log2_spec b Hb) as (LEb,_).
- apply le_succ_l in H.
- apply (pow_le_mono_r_iff 2) in H; order_pos.
+ - rewrite (log2_nonpos b) in H; trivial.
+ generalize (log2_nonneg a); order.
+ - destruct (le_gt_cases a 0) as [Ha|Ha]. + order.
+ + destruct (log2_spec a Ha) as (_,LTa).
+ destruct (log2_spec b Hb) as (LEb,_).
+ apply le_succ_l in H.
+ apply (pow_le_mono_r_iff 2) in H; order_pos.
Qed.
(** When left side is a power of 2, we have an equivalence for <= *)
@@ -208,12 +208,12 @@ Lemma log2_le_pow2 : forall a b, 0<a -> (2^b<=a <-> b <= log2 a).
Proof.
intros a b Ha.
split; intros H.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- generalize (log2_nonneg a); order.
- rewrite <- (log2_pow2 b); trivial. now apply log2_le_mono.
- transitivity (2^(log2 a)).
- apply pow_le_mono_r; order'.
- now destruct (log2_spec a Ha).
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + generalize (log2_nonneg a); order.
+ + rewrite <- (log2_pow2 b); trivial. now apply log2_le_mono.
+ - transitivity (2^(log2 a)).
+ + apply pow_le_mono_r; order'.
+ + now destruct (log2_spec a Ha).
Qed.
(** When right side is a square, we have an equivalence for < *)
@@ -222,15 +222,15 @@ Lemma log2_lt_pow2 : forall a b, 0<a -> (a<2^b <-> log2 a < b).
Proof.
intros a b Ha.
split; intros H.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite pow_neg_r in H; order.
- apply (pow_lt_mono_r_iff 2); try order_pos.
- apply le_lt_trans with a; trivial.
- now destruct (log2_spec a Ha).
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- generalize (log2_nonneg a); order.
- apply log2_lt_cancel; try order.
- now rewrite log2_pow2.
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + rewrite pow_neg_r in H; order.
+ + apply (pow_lt_mono_r_iff 2); try order_pos.
+ apply le_lt_trans with a; trivial.
+ now destruct (log2_spec a Ha).
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + generalize (log2_nonneg a); order.
+ + apply log2_lt_cancel; try order.
+ now rewrite log2_pow2.
Qed.
(** Comparing log2 and identity *)
@@ -240,16 +240,16 @@ Proof.
intros a Ha.
apply (pow_lt_mono_r_iff 2); try order_pos.
apply le_lt_trans with a.
- now destruct (log2_spec a Ha).
- apply pow_gt_lin_r; order'.
+ - now destruct (log2_spec a Ha).
+ - apply pow_gt_lin_r; order'.
Qed.
Lemma log2_le_lin : forall a, 0<=a -> log2 a <= a.
Proof.
intros a Ha.
le_elim Ha.
- now apply lt_le_incl, log2_lt_lin.
- rewrite <- Ha, log2_nonpos; order.
+ - now apply lt_le_incl, log2_lt_lin.
+ - rewrite <- Ha, log2_nonpos; order.
Qed.
(** Log2 and multiplication. *)
@@ -271,14 +271,14 @@ Lemma log2_mul_above : forall a b, 0<=a -> 0<=b ->
Proof.
intros a b Ha Hb.
le_elim Ha.
- le_elim Hb.
- apply lt_succ_r.
- rewrite add_1_r, <- add_succ_r, <- add_succ_l.
- apply log2_lt_pow2; try order_pos.
- rewrite pow_add_r by order_pos.
- apply mul_lt_mono_nonneg; try order; now apply log2_spec.
- rewrite <- Hb. nzsimpl. rewrite log2_nonpos; order_pos.
- rewrite <- Ha. nzsimpl. rewrite log2_nonpos; order_pos.
+ - le_elim Hb.
+ + apply lt_succ_r.
+ rewrite add_1_r, <- add_succ_r, <- add_succ_l.
+ apply log2_lt_pow2; try order_pos.
+ rewrite pow_add_r by order_pos.
+ apply mul_lt_mono_nonneg; try order; now apply log2_spec.
+ + rewrite <- Hb. nzsimpl. rewrite log2_nonpos; order_pos.
+ - rewrite <- Ha. nzsimpl. rewrite log2_nonpos; order_pos.
Qed.
(** And we can't find better approximations in general.
@@ -293,10 +293,10 @@ Lemma log2_mul_pow2 : forall a b, 0<a -> 0<=b -> log2 (a*2^b) == b + log2 a.
Proof.
intros a b Ha Hb.
apply log2_unique; try order_pos. split.
- rewrite pow_add_r, mul_comm; try order_pos.
- apply mul_le_mono_nonneg_r. order_pos. now apply log2_spec.
- rewrite <-add_succ_r, pow_add_r, mul_comm; try order_pos.
- apply mul_lt_mono_pos_l. order_pos. now apply log2_spec.
+ - rewrite pow_add_r, mul_comm; try order_pos.
+ apply mul_le_mono_nonneg_r. + order_pos. + now apply log2_spec.
+ - rewrite <-add_succ_r, pow_add_r, mul_comm; try order_pos.
+ apply mul_lt_mono_pos_l. + order_pos. + now apply log2_spec.
Qed.
Lemma log2_double : forall a, 0<a -> log2 (2*a) == S (log2 a).
@@ -323,13 +323,13 @@ Lemma log2_succ_le : forall a, log2 (S a) <= S (log2 a).
Proof.
intros a.
destruct (lt_trichotomy 0 a) as [LT|[EQ|LT]].
- apply (pow_le_mono_r_iff 2); try order_pos.
- transitivity (S a).
- apply log2_spec.
- apply lt_succ_r; order.
- now apply le_succ_l, log2_spec.
- rewrite <- EQ, <- one_succ, log2_1; order_pos.
- rewrite 2 log2_nonpos. order_pos. order'. now rewrite le_succ_l.
+ - apply (pow_le_mono_r_iff 2); try order_pos.
+ transitivity (S a).
+ + apply log2_spec.
+ apply lt_succ_r; order.
+ + now apply le_succ_l, log2_spec.
+ - rewrite <- EQ, <- one_succ, log2_1; order_pos.
+ - rewrite 2 log2_nonpos. + order_pos. + order'. + now rewrite le_succ_l.
Qed.
Lemma log2_succ_or : forall a,
@@ -337,8 +337,8 @@ Lemma log2_succ_or : forall a,
Proof.
intros.
destruct (le_gt_cases (log2 (S a)) (log2 a)) as [H|H].
- right. generalize (log2_le_mono _ _ (le_succ_diag_r a)); order.
- left. apply le_succ_l in H. generalize (log2_succ_le a); order.
+ - right. generalize (log2_le_mono _ _ (le_succ_diag_r a)); order.
+ - left. apply le_succ_l in H. generalize (log2_succ_le a); order.
Qed.
Lemma log2_eq_succ_is_pow2 : forall a,
@@ -346,27 +346,27 @@ Lemma log2_eq_succ_is_pow2 : forall a,
Proof.
intros a H.
destruct (le_gt_cases a 0) as [Ha|Ha].
- rewrite 2 (proj2 (log2_null _)) in H. generalize (lt_succ_diag_r 0); order.
- order'. apply le_succ_l. order'.
- assert (Ha' : 0 < S a) by (apply lt_succ_r; order).
- exists (log2 (S a)).
- generalize (proj1 (log2_spec (S a) Ha')) (proj2 (log2_spec a Ha)).
- rewrite <- le_succ_l, <- H. order.
+ - rewrite 2 (proj2 (log2_null _)) in H. + generalize (lt_succ_diag_r 0); order.
+ + order'. + apply le_succ_l. order'.
+ - assert (Ha' : 0 < S a) by (apply lt_succ_r; order).
+ exists (log2 (S a)).
+ generalize (proj1 (log2_spec (S a) Ha')) (proj2 (log2_spec a Ha)).
+ rewrite <- le_succ_l, <- H. order.
Qed.
Lemma log2_eq_succ_iff_pow2 : forall a, 0<a ->
(log2 (S a) == S (log2 a) <-> exists b, S a == 2^b).
Proof.
intros a Ha.
- split. apply log2_eq_succ_is_pow2.
- intros (b,Hb).
- assert (Hb' : 0 < b).
- apply (pow_gt_1 2); try order'; now rewrite <- Hb, one_succ, <- succ_lt_mono.
- rewrite Hb, log2_pow2; try order'.
- setoid_replace a with (P (2^b)). rewrite log2_pred_pow2; trivial.
- symmetry; now apply lt_succ_pred with 0.
- apply succ_inj. rewrite Hb. symmetry. apply lt_succ_pred with 0.
- rewrite <- Hb, lt_succ_r; order.
+ split. - apply log2_eq_succ_is_pow2.
+ - intros (b,Hb).
+ assert (Hb' : 0 < b).
+ + apply (pow_gt_1 2); try order'; now rewrite <- Hb, one_succ, <- succ_lt_mono.
+ + rewrite Hb, log2_pow2; try order'.
+ setoid_replace a with (P (2^b)). * rewrite log2_pred_pow2; trivial.
+ symmetry; now apply lt_succ_pred with 0.
+ * apply succ_inj. rewrite Hb. symmetry. apply lt_succ_pred with 0.
+ rewrite <- Hb, lt_succ_r; order.
Qed.
Lemma log2_succ_double : forall a, 0<a -> log2 (2*a+1) == S (log2 a).
@@ -376,18 +376,18 @@ Proof.
destruct (log2_succ_or (2*a)) as [H|H]; [exfalso|now rewrite H, log2_double].
apply log2_eq_succ_is_pow2 in H. destruct H as (b,H).
destruct (lt_trichotomy b 0) as [LT|[EQ|LT]].
- rewrite pow_neg_r in H; trivial.
- apply (mul_pos_pos 2), succ_lt_mono in Ha; try order'.
- rewrite <- one_succ in Ha. order'.
- rewrite EQ, pow_0_r in H.
- apply (mul_pos_pos 2), succ_lt_mono in Ha; try order'.
- rewrite <- one_succ in Ha. order'.
- assert (EQ:=lt_succ_pred 0 b LT).
- rewrite <- EQ, pow_succ_r in H; [|now rewrite <- lt_succ_r, EQ].
- destruct (lt_ge_cases a (2^(P b))) as [LT'|LE'].
- generalize (mul_2_mono_l _ _ LT'). rewrite add_1_l. order.
- rewrite (mul_le_mono_pos_l _ _ 2) in LE'; try order'.
- rewrite <- H in LE'. apply le_succ_l in LE'. order.
+ - rewrite pow_neg_r in H; trivial.
+ apply (mul_pos_pos 2), succ_lt_mono in Ha; try order'.
+ rewrite <- one_succ in Ha. order'.
+ - rewrite EQ, pow_0_r in H.
+ apply (mul_pos_pos 2), succ_lt_mono in Ha; try order'.
+ rewrite <- one_succ in Ha. order'.
+ - assert (EQ:=lt_succ_pred 0 b LT).
+ rewrite <- EQ, pow_succ_r in H; [|now rewrite <- lt_succ_r, EQ].
+ destruct (lt_ge_cases a (2^(P b))) as [LT'|LE'].
+ + generalize (mul_2_mono_l _ _ LT'). rewrite add_1_l. order.
+ + rewrite (mul_le_mono_pos_l _ _ 2) in LE'; try order'.
+ rewrite <- H in LE'. apply le_succ_l in LE'. order.
Qed.
(** Log2 and addition *)
@@ -396,25 +396,28 @@ Lemma log2_add_le : forall a b, a~=1 -> b~=1 -> log2 (a+b) <= log2 a + log2 b.
Proof.
intros a b Ha Hb.
destruct (lt_trichotomy a 1) as [Ha'|[Ha'|Ha']]; [|order|].
- rewrite one_succ, lt_succ_r in Ha'.
- rewrite (log2_nonpos a); trivial. nzsimpl. apply log2_le_mono.
- rewrite <- (add_0_l b) at 2. now apply add_le_mono.
- destruct (lt_trichotomy b 1) as [Hb'|[Hb'|Hb']]; [|order|].
- rewrite one_succ, lt_succ_r in Hb'.
- rewrite (log2_nonpos b); trivial. nzsimpl. apply log2_le_mono.
- rewrite <- (add_0_r a) at 2. now apply add_le_mono.
- clear Ha Hb.
- apply lt_succ_r.
- apply log2_lt_pow2; try order_pos.
- rewrite pow_succ_r by order_pos.
- rewrite two_succ, one_succ at 1. nzsimpl.
- apply add_lt_mono.
- apply lt_le_trans with (2^(S (log2 a))). apply log2_spec; order'.
- apply pow_le_mono_r. order'. rewrite <- add_1_r. apply add_le_mono_l.
- rewrite one_succ; now apply le_succ_l, log2_pos.
- apply lt_le_trans with (2^(S (log2 b))). apply log2_spec; order'.
- apply pow_le_mono_r. order'. rewrite <- add_1_l. apply add_le_mono_r.
- rewrite one_succ; now apply le_succ_l, log2_pos.
+ - rewrite one_succ, lt_succ_r in Ha'.
+ rewrite (log2_nonpos a); trivial. nzsimpl. apply log2_le_mono.
+ rewrite <- (add_0_l b) at 2. now apply add_le_mono.
+ - destruct (lt_trichotomy b 1) as [Hb'|[Hb'|Hb']]; [|order|].
+ + rewrite one_succ, lt_succ_r in Hb'.
+ rewrite (log2_nonpos b); trivial. nzsimpl. apply log2_le_mono.
+ rewrite <- (add_0_r a) at 2. now apply add_le_mono.
+ + clear Ha Hb.
+ apply lt_succ_r.
+ apply log2_lt_pow2; try order_pos.
+ rewrite pow_succ_r by order_pos.
+ rewrite two_succ, one_succ at 1. nzsimpl.
+ apply add_lt_mono.
+ * apply lt_le_trans with (2^(S (log2 a))). -- apply log2_spec; order'.
+ -- apply pow_le_mono_r. ++ order'.
+ ++ rewrite <- add_1_r. apply add_le_mono_l.
+ rewrite one_succ; now apply le_succ_l, log2_pos.
+ * apply lt_le_trans with (2^(S (log2 b))).
+ -- apply log2_spec; order'.
+ -- apply pow_le_mono_r. ++ order'.
+ ++ rewrite <- add_1_l. apply add_le_mono_r.
+ rewrite one_succ; now apply le_succ_l, log2_pos.
Qed.
(** The sum of two log2 is less than twice the log2 of the sum.
@@ -430,17 +433,17 @@ Lemma add_log2_lt : forall a b, 0<a -> 0<b ->
Proof.
intros a b Ha Hb. nzsimpl'.
assert (H : log2 a <= log2 (a+b)).
- apply log2_le_mono. rewrite <- (add_0_r a) at 1. apply add_le_mono; order.
- assert (H' : log2 b <= log2 (a+b)).
- apply log2_le_mono. rewrite <- (add_0_l b) at 1. apply add_le_mono; order.
- le_elim H.
- apply lt_le_trans with (log2 (a+b) + log2 b).
- now apply add_lt_mono_r. now apply add_le_mono_l.
- rewrite <- H at 1. apply add_lt_mono_l.
- le_elim H'; trivial.
- symmetry in H. apply log2_same in H; try order_pos.
- symmetry in H'. apply log2_same in H'; try order_pos.
- revert H H'. nzsimpl'. rewrite <- add_lt_mono_l, <- add_lt_mono_r; order.
+ - apply log2_le_mono. rewrite <- (add_0_r a) at 1. apply add_le_mono; order.
+ - assert (H' : log2 b <= log2 (a+b)).
+ + apply log2_le_mono. rewrite <- (add_0_l b) at 1. apply add_le_mono; order.
+ + le_elim H.
+ * apply lt_le_trans with (log2 (a+b) + log2 b).
+ -- now apply add_lt_mono_r. -- now apply add_le_mono_l.
+ * rewrite <- H at 1. apply add_lt_mono_l.
+ le_elim H'; trivial.
+ symmetry in H. apply log2_same in H; try order_pos.
+ symmetry in H'. apply log2_same in H'; try order_pos.
+ revert H H'. nzsimpl'. rewrite <- add_lt_mono_l, <- add_lt_mono_r; order.
Qed.
End NZLog2Prop.
@@ -493,9 +496,9 @@ Qed.
Instance log2_up_wd : Proper (eq==>eq) log2_up.
Proof.
assert (Proper (eq==>eq==>Logic.eq) compare).
- repeat red; intros; do 2 case compare_spec; trivial; order.
- intros a a' Ha. unfold log2_up. rewrite Ha at 1.
- case compare; now rewrite ?Ha.
+ - repeat red; intros; do 2 case compare_spec; trivial; order.
+ - intros a a' Ha. unfold log2_up. rewrite Ha at 1.
+ case compare; now rewrite ?Ha.
Qed.
(** [log2_up] is always non-negative *)
@@ -512,22 +515,23 @@ Lemma log2_up_unique : forall a b, 0<b -> 2^(P b)<a<=2^b -> log2_up a == b.
Proof.
intros a b Hb (LEb,LTb).
assert (Ha : 1 < a).
- apply le_lt_trans with (2^(P b)); trivial.
- rewrite one_succ. apply le_succ_l.
- apply pow_pos_nonneg. order'. apply lt_succ_r.
- now rewrite (lt_succ_pred 0 b Hb).
- assert (Hc := log2_up_nonneg a).
- destruct (log2_up_spec a Ha) as (LTc,LEc).
- assert (b <= log2_up a).
- apply lt_succ_r. rewrite <- (lt_succ_pred 0 b Hb).
- rewrite <- succ_lt_mono.
- apply (pow_lt_mono_r_iff 2); try order'.
- assert (Hc' : 0 < log2_up a) by order.
- assert (log2_up a <= b).
- apply lt_succ_r. rewrite <- (lt_succ_pred 0 _ Hc').
- rewrite <- succ_lt_mono.
- apply (pow_lt_mono_r_iff 2); try order'.
- order.
+ - apply le_lt_trans with (2^(P b)); trivial.
+ rewrite one_succ. apply le_succ_l.
+ apply pow_pos_nonneg. + order'.
+ + apply lt_succ_r.
+ now rewrite (lt_succ_pred 0 b Hb).
+ - assert (Hc := log2_up_nonneg a).
+ destruct (log2_up_spec a Ha) as (LTc,LEc).
+ assert (b <= log2_up a).
+ + apply lt_succ_r. rewrite <- (lt_succ_pred 0 b Hb).
+ rewrite <- succ_lt_mono.
+ apply (pow_lt_mono_r_iff 2); try order'.
+ + assert (Hc' : 0 < log2_up a) by order.
+ assert (log2_up a <= b).
+ * apply lt_succ_r. rewrite <- (lt_succ_pred 0 _ Hc').
+ rewrite <- succ_lt_mono.
+ apply (pow_lt_mono_r_iff 2); try order'.
+ * order.
Qed.
(** [log2_up] is exact on powers of 2 *)
@@ -536,12 +540,12 @@ Lemma log2_up_pow2 : forall a, 0<=a -> log2_up (2^a) == a.
Proof.
intros a Ha.
le_elim Ha.
- apply log2_up_unique; trivial.
- split; try order.
- apply pow_lt_mono_r; try order'.
- rewrite <- (lt_succ_pred 0 a Ha) at 2.
- now apply lt_succ_r.
- now rewrite <- Ha, pow_0_r, log2_up_eqn0.
+ - apply log2_up_unique; trivial.
+ split; try order.
+ apply pow_lt_mono_r; try order'.
+ rewrite <- (lt_succ_pred 0 a Ha) at 2.
+ now apply lt_succ_r.
+ - now rewrite <- Ha, pow_0_r, log2_up_eqn0.
Qed.
(** [log2_up] and successors of powers of 2 *)
@@ -570,9 +574,9 @@ Qed.
Lemma le_log2_log2_up : forall a, log2 a <= log2_up a.
Proof.
intros a. unfold log2_up. case compare_spec; intros H.
- rewrite <- H, log2_1. order.
- rewrite <- (lt_succ_pred 1 a H) at 1. apply log2_succ_le.
- rewrite log2_nonpos. order. now rewrite <-lt_succ_r, <-one_succ.
+ - rewrite <- H, log2_1. order.
+ - rewrite <- (lt_succ_pred 1 a H) at 1. apply log2_succ_le.
+ - rewrite log2_nonpos. + order. + now rewrite <-lt_succ_r, <-one_succ.
Qed.
Lemma le_log2_up_succ_log2 : forall a, log2_up a <= S (log2 a).
@@ -586,23 +590,24 @@ Lemma log2_log2_up_spec : forall a, 0<a ->
2^log2 a <= a <= 2^log2_up a.
Proof.
intros a H. split.
- now apply log2_spec.
- rewrite <-le_succ_l, <-one_succ in H. le_elim H.
- now apply log2_up_spec.
- now rewrite <-H, log2_up_1, pow_0_r.
+ - now apply log2_spec.
+ - rewrite <-le_succ_l, <-one_succ in H. le_elim H.
+ + now apply log2_up_spec.
+ + now rewrite <-H, log2_up_1, pow_0_r.
Qed.
Lemma log2_log2_up_exact :
forall a, 0<a -> (log2 a == log2_up a <-> exists b, a == 2^b).
Proof.
intros a Ha.
- split. intros. exists (log2 a).
- generalize (log2_log2_up_spec a Ha). rewrite <-H.
- destruct 1; order.
- intros (b,Hb). rewrite Hb.
- destruct (le_gt_cases 0 b).
- now rewrite log2_pow2, log2_up_pow2.
- rewrite pow_neg_r; trivial. now rewrite log2_nonpos, log2_up_nonpos.
+ split.
+ - intros. exists (log2 a).
+ generalize (log2_log2_up_spec a Ha). rewrite <-H.
+ destruct 1; order.
+ - intros (b,Hb). rewrite Hb.
+ destruct (le_gt_cases 0 b).
+ + now rewrite log2_pow2, log2_up_pow2.
+ + rewrite pow_neg_r; trivial. now rewrite log2_nonpos, log2_up_nonpos.
Qed.
(** [log2_up] n is strictly positive for 1<n *)
@@ -617,9 +622,9 @@ Qed.
Lemma log2_up_null : forall a, log2_up a == 0 <-> a <= 1.
Proof.
intros a. split; intros H.
- destruct (le_gt_cases a 1) as [Ha|Ha]; trivial.
- generalize (log2_up_pos a Ha); order.
- now apply log2_up_eqn0.
+ - destruct (le_gt_cases a 1) as [Ha|Ha]; trivial.
+ generalize (log2_up_pos a Ha); order.
+ - now apply log2_up_eqn0.
Qed.
(** [log2_up] is a monotone function (but not a strict one) *)
@@ -628,10 +633,10 @@ Lemma log2_up_le_mono : forall a b, a<=b -> log2_up a <= log2_up b.
Proof.
intros a b H.
destruct (le_gt_cases a 1) as [Ha|Ha].
- rewrite log2_up_eqn0; trivial. apply log2_up_nonneg.
- rewrite 2 log2_up_eqn; try order.
- rewrite <- succ_le_mono. apply log2_le_mono, succ_le_mono.
- rewrite 2 lt_succ_pred with 1; order.
+ - rewrite log2_up_eqn0; trivial. apply log2_up_nonneg.
+ - rewrite 2 log2_up_eqn; try order.
+ rewrite <- succ_le_mono. apply log2_le_mono, succ_le_mono.
+ rewrite 2 lt_succ_pred with 1; order.
Qed.
(** No reverse result for <=, consider for instance log2_up 4 <= log2_up 3 *)
@@ -640,12 +645,12 @@ Lemma log2_up_lt_cancel : forall a b, log2_up a < log2_up b -> a < b.
Proof.
intros a b H.
destruct (le_gt_cases b 1) as [Hb|Hb].
- rewrite (log2_up_eqn0 b) in H; trivial.
- generalize (log2_up_nonneg a); order.
- destruct (le_gt_cases a 1) as [Ha|Ha]. order.
- rewrite 2 log2_up_eqn in H; try order.
- rewrite <- succ_lt_mono in H. apply log2_lt_cancel, succ_lt_mono in H.
- rewrite 2 lt_succ_pred with 1 in H; order.
+ - rewrite (log2_up_eqn0 b) in H; trivial.
+ generalize (log2_up_nonneg a); order.
+ - destruct (le_gt_cases a 1) as [Ha|Ha]. + order.
+ + rewrite 2 log2_up_eqn in H; try order.
+ rewrite <- succ_lt_mono in H. apply log2_lt_cancel, succ_lt_mono in H.
+ rewrite 2 lt_succ_pred with 1 in H; order.
Qed.
(** When left side is a power of 2, we have an equivalence for < *)
@@ -654,16 +659,16 @@ Lemma log2_up_lt_pow2 : forall a b, 0<a -> (2^b<a <-> b < log2_up a).
Proof.
intros a b Ha.
split; intros H.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- generalize (log2_up_nonneg a); order.
- apply (pow_lt_mono_r_iff 2). order'. apply log2_up_nonneg.
- apply lt_le_trans with a; trivial.
- apply (log2_up_spec a).
- apply le_lt_trans with (2^b); trivial.
- rewrite one_succ, le_succ_l. apply pow_pos_nonneg; order'.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- now rewrite pow_neg_r.
- rewrite <- (log2_up_pow2 b) in H; trivial. now apply log2_up_lt_cancel.
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + generalize (log2_up_nonneg a); order.
+ + apply (pow_lt_mono_r_iff 2). * order'. * apply log2_up_nonneg.
+ * apply lt_le_trans with a; trivial.
+ apply (log2_up_spec a).
+ apply le_lt_trans with (2^b); trivial.
+ rewrite one_succ, le_succ_l. apply pow_pos_nonneg; order'.
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + now rewrite pow_neg_r.
+ + rewrite <- (log2_up_pow2 b) in H; trivial. now apply log2_up_lt_cancel.
Qed.
(** When right side is a square, we have an equivalence for <= *)
@@ -672,12 +677,12 @@ Lemma log2_up_le_pow2 : forall a b, 0<a -> (a<=2^b <-> log2_up a <= b).
Proof.
intros a b Ha.
split; intros H.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite pow_neg_r in H; order.
- rewrite <- (log2_up_pow2 b); trivial. now apply log2_up_le_mono.
- transitivity (2^(log2_up a)).
- now apply log2_log2_up_spec.
- apply pow_le_mono_r; order'.
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + rewrite pow_neg_r in H; order.
+ + rewrite <- (log2_up_pow2 b); trivial. now apply log2_up_le_mono.
+ - transitivity (2^(log2_up a)).
+ + now apply log2_log2_up_spec.
+ + apply pow_le_mono_r; order'.
Qed.
(** Comparing [log2_up] and identity *)
@@ -688,15 +693,15 @@ Proof.
assert (H : S (P a) == a) by (now apply lt_succ_pred with 0).
rewrite <- H at 2. apply lt_succ_r. apply log2_up_le_pow2; trivial.
rewrite <- H at 1. apply le_succ_l.
- apply pow_gt_lin_r. order'. apply lt_succ_r; order.
+ apply pow_gt_lin_r. - order'. - apply lt_succ_r; order.
Qed.
Lemma log2_up_le_lin : forall a, 0<=a -> log2_up a <= a.
Proof.
intros a Ha.
le_elim Ha.
- now apply lt_le_incl, log2_up_lt_lin.
- rewrite <- Ha, log2_up_nonpos; order.
+ - now apply lt_le_incl, log2_up_lt_lin.
+ - rewrite <- Ha, log2_up_nonpos; order.
Qed.
(** [log2_up] and multiplication. *)
@@ -711,12 +716,12 @@ Proof.
assert (Ha':=log2_up_nonneg a).
assert (Hb':=log2_up_nonneg b).
le_elim Ha.
- le_elim Hb.
- apply log2_up_le_pow2; try order_pos.
- rewrite pow_add_r; trivial.
- apply mul_le_mono_nonneg; try apply log2_log2_up_spec; order'.
- rewrite <- Hb. nzsimpl. rewrite log2_up_nonpos; order_pos.
- rewrite <- Ha. nzsimpl. rewrite log2_up_nonpos; order_pos.
+ - le_elim Hb.
+ + apply log2_up_le_pow2; try order_pos.
+ rewrite pow_add_r; trivial.
+ apply mul_le_mono_nonneg; try apply log2_log2_up_spec; order'.
+ + rewrite <- Hb. nzsimpl. rewrite log2_up_nonpos; order_pos.
+ - rewrite <- Ha. nzsimpl. rewrite log2_up_nonpos; order_pos.
Qed.
Lemma log2_up_mul_below : forall a b, 0<a -> 0<b ->
@@ -724,21 +729,21 @@ Lemma log2_up_mul_below : forall a b, 0<a -> 0<b ->
Proof.
intros a b Ha Hb.
rewrite <-le_succ_l, <-one_succ in Ha. le_elim Ha.
- rewrite <-le_succ_l, <-one_succ in Hb. le_elim Hb.
- assert (Ha' : 0 < log2_up a) by (apply log2_up_pos; trivial).
- assert (Hb' : 0 < log2_up b) by (apply log2_up_pos; trivial).
- rewrite <- (lt_succ_pred 0 (log2_up a)); trivial.
- rewrite <- (lt_succ_pred 0 (log2_up b)); trivial.
- nzsimpl. rewrite <- succ_le_mono, le_succ_l.
- apply (pow_lt_mono_r_iff 2). order'. apply log2_up_nonneg.
- rewrite pow_add_r; try (apply lt_succ_r; rewrite (lt_succ_pred 0); trivial).
- apply lt_le_trans with (a*b).
- apply mul_lt_mono_nonneg; try order_pos; try now apply log2_up_spec.
- apply log2_up_spec.
- setoid_replace 1 with (1*1) by now nzsimpl.
- apply mul_lt_mono_nonneg; order'.
- rewrite <- Hb, log2_up_1; nzsimpl. apply le_succ_diag_r.
- rewrite <- Ha, log2_up_1; nzsimpl. apply le_succ_diag_r.
+ - rewrite <-le_succ_l, <-one_succ in Hb. le_elim Hb.
+ + assert (Ha' : 0 < log2_up a) by (apply log2_up_pos; trivial).
+ assert (Hb' : 0 < log2_up b) by (apply log2_up_pos; trivial).
+ rewrite <- (lt_succ_pred 0 (log2_up a)); trivial.
+ rewrite <- (lt_succ_pred 0 (log2_up b)); trivial.
+ nzsimpl. rewrite <- succ_le_mono, le_succ_l.
+ apply (pow_lt_mono_r_iff 2). * order'. * apply log2_up_nonneg.
+ * rewrite pow_add_r; try (apply lt_succ_r; rewrite (lt_succ_pred 0); trivial).
+ apply lt_le_trans with (a*b).
+ -- apply mul_lt_mono_nonneg; try order_pos; try now apply log2_up_spec.
+ -- apply log2_up_spec.
+ setoid_replace 1 with (1*1) by now nzsimpl.
+ apply mul_lt_mono_nonneg; order'.
+ + rewrite <- Hb, log2_up_1; nzsimpl. apply le_succ_diag_r.
+ - rewrite <- Ha, log2_up_1; nzsimpl. apply le_succ_diag_r.
Qed.
(** And we can't find better approximations in general.
@@ -754,16 +759,16 @@ Lemma log2_up_mul_pow2 : forall a b, 0<a -> 0<=b ->
Proof.
intros a b Ha Hb.
rewrite <- le_succ_l, <- one_succ in Ha; le_elim Ha.
- apply log2_up_unique. apply add_nonneg_pos; trivial. now apply log2_up_pos.
- split.
- assert (EQ := lt_succ_pred 0 _ (log2_up_pos _ Ha)).
- rewrite <- EQ. nzsimpl. rewrite pow_add_r, mul_comm; trivial.
- apply mul_lt_mono_pos_r. order_pos. now apply log2_up_spec.
- rewrite <- lt_succ_r, EQ. now apply log2_up_pos.
- rewrite pow_add_r, mul_comm; trivial.
- apply mul_le_mono_nonneg_l. order_pos. now apply log2_up_spec.
- apply log2_up_nonneg.
- now rewrite <- Ha, mul_1_l, log2_up_1, add_0_r, log2_up_pow2.
+ - apply log2_up_unique. + apply add_nonneg_pos; trivial. now apply log2_up_pos.
+ + split.
+ * assert (EQ := lt_succ_pred 0 _ (log2_up_pos _ Ha)).
+ rewrite <- EQ. nzsimpl. rewrite pow_add_r, mul_comm; trivial.
+ -- apply mul_lt_mono_pos_r. ++ order_pos. ++ now apply log2_up_spec.
+ -- rewrite <- lt_succ_r, EQ. now apply log2_up_pos.
+ * rewrite pow_add_r, mul_comm; trivial.
+ -- apply mul_le_mono_nonneg_l. ++ order_pos. ++ now apply log2_up_spec.
+ -- apply log2_up_nonneg.
+ - now rewrite <- Ha, mul_1_l, log2_up_1, add_0_r, log2_up_pow2.
Qed.
Lemma log2_up_double : forall a, 0<a -> log2_up (2*a) == S (log2_up a).
@@ -790,12 +795,12 @@ Lemma log2_up_succ_le : forall a, log2_up (S a) <= S (log2_up a).
Proof.
intros a.
destruct (lt_trichotomy 1 a) as [LT|[EQ|LT]].
- rewrite 2 log2_up_eqn; trivial.
- rewrite pred_succ, <- succ_le_mono. rewrite <-(lt_succ_pred 1 a LT) at 1.
- apply log2_succ_le.
- apply lt_succ_r; order.
- rewrite <- EQ, <- two_succ, log2_up_1, log2_up_2. now nzsimpl'.
- rewrite 2 log2_up_eqn0. order_pos. order'. now rewrite le_succ_l.
+ - rewrite 2 log2_up_eqn; trivial.
+ + rewrite pred_succ, <- succ_le_mono. rewrite <-(lt_succ_pred 1 a LT) at 1.
+ apply log2_succ_le.
+ + apply lt_succ_r; order.
+ - rewrite <- EQ, <- two_succ, log2_up_1, log2_up_2. now nzsimpl'.
+ - rewrite 2 log2_up_eqn0. + order_pos. + order'. + now rewrite le_succ_l.
Qed.
Lemma log2_up_succ_or : forall a,
@@ -803,8 +808,8 @@ Lemma log2_up_succ_or : forall a,
Proof.
intros.
destruct (le_gt_cases (log2_up (S a)) (log2_up a)).
- right. generalize (log2_up_le_mono _ _ (le_succ_diag_r a)); order.
- left. apply le_succ_l in H. generalize (log2_up_succ_le a); order.
+ - right. generalize (log2_up_le_mono _ _ (le_succ_diag_r a)); order.
+ - left. apply le_succ_l in H. generalize (log2_up_succ_le a); order.
Qed.
Lemma log2_up_eq_succ_is_pow2 : forall a,
@@ -812,33 +817,33 @@ Lemma log2_up_eq_succ_is_pow2 : forall a,
Proof.
intros a H.
destruct (le_gt_cases a 0) as [Ha|Ha].
- rewrite 2 (proj2 (log2_up_null _)) in H. generalize (lt_succ_diag_r 0); order.
- order'. apply le_succ_l. order'.
- assert (Ha' : 1 < S a) by (now rewrite one_succ, <- succ_lt_mono).
- exists (log2_up a).
- generalize (proj1 (log2_up_spec (S a) Ha')) (proj2 (log2_log2_up_spec a Ha)).
- rewrite H, pred_succ, lt_succ_r. order.
+ - rewrite 2 (proj2 (log2_up_null _)) in H. + generalize (lt_succ_diag_r 0); order.
+ + order'. + apply le_succ_l. order'.
+ - assert (Ha' : 1 < S a) by (now rewrite one_succ, <- succ_lt_mono).
+ exists (log2_up a).
+ generalize (proj1 (log2_up_spec (S a) Ha')) (proj2 (log2_log2_up_spec a Ha)).
+ rewrite H, pred_succ, lt_succ_r. order.
Qed.
Lemma log2_up_eq_succ_iff_pow2 : forall a, 0<a ->
(log2_up (S a) == S (log2_up a) <-> exists b, a == 2^b).
Proof.
intros a Ha.
- split. apply log2_up_eq_succ_is_pow2.
- intros (b,Hb).
- destruct (lt_ge_cases b 0) as [Hb'|Hb'].
- rewrite pow_neg_r in Hb; order.
- rewrite Hb, log2_up_pow2; try order'.
- now rewrite log2_up_succ_pow2.
+ split. - apply log2_up_eq_succ_is_pow2.
+ - intros (b,Hb).
+ destruct (lt_ge_cases b 0) as [Hb'|Hb'].
+ + rewrite pow_neg_r in Hb; order.
+ + rewrite Hb, log2_up_pow2; try order'.
+ now rewrite log2_up_succ_pow2.
Qed.
Lemma log2_up_succ_double : forall a, 0<a ->
log2_up (2*a+1) == 2 + log2 a.
Proof.
intros a Ha.
- rewrite log2_up_eqn. rewrite add_1_r, pred_succ, log2_double; now nzsimpl'.
- apply le_lt_trans with (0+1). now nzsimpl'.
- apply add_lt_mono_r. order_pos.
+ rewrite log2_up_eqn. - rewrite add_1_r, pred_succ, log2_double; now nzsimpl'.
+ - apply le_lt_trans with (0+1). + now nzsimpl'.
+ + apply add_lt_mono_r. order_pos.
Qed.
(** [log2_up] and addition *)
@@ -848,17 +853,17 @@ Lemma log2_up_add_le : forall a b, a~=1 -> b~=1 ->
Proof.
intros a b Ha Hb.
destruct (lt_trichotomy a 1) as [Ha'|[Ha'|Ha']]; [|order|].
- rewrite (log2_up_eqn0 a) by order. nzsimpl. apply log2_up_le_mono.
- rewrite one_succ, lt_succ_r in Ha'.
- rewrite <- (add_0_l b) at 2. now apply add_le_mono.
- destruct (lt_trichotomy b 1) as [Hb'|[Hb'|Hb']]; [|order|].
- rewrite (log2_up_eqn0 b) by order. nzsimpl. apply log2_up_le_mono.
- rewrite one_succ, lt_succ_r in Hb'.
- rewrite <- (add_0_r a) at 2. now apply add_le_mono.
- clear Ha Hb.
- transitivity (log2_up (a*b)).
- now apply log2_up_le_mono, add_le_mul.
- apply log2_up_mul_above; order'.
+ - rewrite (log2_up_eqn0 a) by order. nzsimpl. apply log2_up_le_mono.
+ rewrite one_succ, lt_succ_r in Ha'.
+ rewrite <- (add_0_l b) at 2. now apply add_le_mono.
+ - destruct (lt_trichotomy b 1) as [Hb'|[Hb'|Hb']]; [|order|].
+ + rewrite (log2_up_eqn0 b) by order. nzsimpl. apply log2_up_le_mono.
+ rewrite one_succ, lt_succ_r in Hb'.
+ rewrite <- (add_0_r a) at 2. now apply add_le_mono.
+ + clear Ha Hb.
+ transitivity (log2_up (a*b)).
+ * now apply log2_up_le_mono, add_le_mul.
+ * apply log2_up_mul_above; order'.
Qed.
(** The sum of two [log2_up] is less than twice the [log2_up] of the sum.
@@ -874,17 +879,17 @@ Lemma add_log2_up_lt : forall a b, 0<a -> 0<b ->
Proof.
intros a b Ha Hb. nzsimpl'.
assert (H : log2_up a <= log2_up (a+b)).
- apply log2_up_le_mono. rewrite <- (add_0_r a) at 1. apply add_le_mono; order.
- assert (H' : log2_up b <= log2_up (a+b)).
- apply log2_up_le_mono. rewrite <- (add_0_l b) at 1. apply add_le_mono; order.
- le_elim H.
- apply lt_le_trans with (log2_up (a+b) + log2_up b).
- now apply add_lt_mono_r. now apply add_le_mono_l.
- rewrite <- H at 1. apply add_lt_mono_l.
- le_elim H'. trivial.
- symmetry in H. apply log2_up_same in H; try order_pos.
- symmetry in H'. apply log2_up_same in H'; try order_pos.
- revert H H'. nzsimpl'. rewrite <- add_lt_mono_l, <- add_lt_mono_r; order.
+ - apply log2_up_le_mono. rewrite <- (add_0_r a) at 1. apply add_le_mono; order.
+ - assert (H' : log2_up b <= log2_up (a+b)).
+ + apply log2_up_le_mono. rewrite <- (add_0_l b) at 1. apply add_le_mono; order.
+ + le_elim H.
+ * apply lt_le_trans with (log2_up (a+b) + log2_up b).
+ -- now apply add_lt_mono_r. -- now apply add_le_mono_l.
+ * rewrite <- H at 1. apply add_lt_mono_l.
+ le_elim H'. -- trivial.
+ -- symmetry in H. apply log2_up_same in H; try order_pos.
+ symmetry in H'. apply log2_up_same in H'; try order_pos.
+ revert H H'. nzsimpl'. rewrite <- add_lt_mono_l, <- add_lt_mono_r; order.
Qed.
End NZLog2UpProp.
diff --git a/theories/Numbers/NatInt/NZMul.v b/theories/Numbers/NatInt/NZMul.v
index 44cbc51712..1492188452 100644
--- a/theories/Numbers/NatInt/NZMul.v
+++ b/theories/Numbers/NatInt/NZMul.v
@@ -22,24 +22,27 @@ Qed.
Theorem mul_succ_r : forall n m, n * (S m) == n * m + n.
Proof.
-intros n m; nzinduct n. now nzsimpl.
-intro n. nzsimpl. rewrite succ_inj_wd, <- add_assoc, (add_comm m n), add_assoc.
-now rewrite add_cancel_r.
+ intros n m; nzinduct n.
+ - now nzsimpl.
+ - intro n. nzsimpl. rewrite succ_inj_wd, <- add_assoc, (add_comm m n), add_assoc.
+ now rewrite add_cancel_r.
Qed.
Hint Rewrite mul_0_r mul_succ_r : nz.
Theorem mul_comm : forall n m, n * m == m * n.
Proof.
-intros n m; nzinduct n. now nzsimpl.
-intro. nzsimpl. now rewrite add_cancel_r.
+ intros n m; nzinduct n.
+ - now nzsimpl.
+ - intro. nzsimpl. now rewrite add_cancel_r.
Qed.
Theorem mul_add_distr_r : forall n m p, (n + m) * p == n * p + m * p.
Proof.
-intros n m p; nzinduct n. now nzsimpl.
-intro n. nzsimpl. rewrite <- add_assoc, (add_comm p (m*p)), add_assoc.
-now rewrite add_cancel_r.
+ intros n m p; nzinduct n.
+ - now nzsimpl.
+ - intro n. nzsimpl. rewrite <- add_assoc, (add_comm p (m*p)), add_assoc.
+ now rewrite add_cancel_r.
Qed.
Theorem mul_add_distr_l : forall n m p, n * (m + p) == n * m + n * p.
@@ -51,9 +54,9 @@ Qed.
Theorem mul_assoc : forall n m p, n * (m * p) == (n * m) * p.
Proof.
-intros n m p; nzinduct n. now nzsimpl.
-intro n. nzsimpl. rewrite mul_add_distr_r.
-now rewrite add_cancel_r.
+ intros n m p; nzinduct n. - now nzsimpl.
+ - intro n. nzsimpl. rewrite mul_add_distr_r.
+ now rewrite add_cancel_r.
Qed.
Theorem mul_1_l : forall n, 1 * n == n.
diff --git a/theories/Numbers/NatInt/NZMulOrder.v b/theories/Numbers/NatInt/NZMulOrder.v
index 292f0837c0..dc4167e96f 100644
--- a/theories/Numbers/NatInt/NZMulOrder.v
+++ b/theories/Numbers/NatInt/NZMulOrder.v
@@ -26,16 +26,16 @@ Qed.
Theorem mul_lt_mono_pos_l : forall p n m, 0 < p -> (n < m <-> p * n < p * m).
Proof.
-intros p n m Hp. revert n m. apply lt_ind with (4:=Hp). solve_proper.
-intros. now nzsimpl.
-clear p Hp. intros p Hp IH n m. nzsimpl.
-assert (LR : forall n m, n < m -> p * n + n < p * m + m)
- by (intros n1 m1 H; apply add_lt_mono; trivial; now rewrite <- IH).
-split; intros H.
-now apply LR.
-destruct (lt_trichotomy n m) as [LT|[EQ|GT]]; trivial.
-rewrite EQ in H. order.
-apply LR in GT. order.
+ intros p n m Hp. revert n m. apply lt_ind with (4:=Hp). - solve_proper.
+ - intros. now nzsimpl.
+ - clear p Hp. intros p Hp IH n m. nzsimpl.
+ assert (LR : forall n m, n < m -> p * n + n < p * m + m)
+ by (intros n1 m1 H; apply add_lt_mono; trivial; now rewrite <- IH).
+ split; intros H.
+ + now apply LR.
+ + destruct (lt_trichotomy n m) as [LT|[EQ|GT]]; trivial.
+ * rewrite EQ in H. order.
+ * apply LR in GT. order.
Qed.
Theorem mul_lt_mono_pos_r : forall p n m, 0 < p -> (n < m <-> n * p < m * p).
@@ -47,19 +47,20 @@ Qed.
Theorem mul_lt_mono_neg_l : forall p n m, p < 0 -> (n < m <-> p * m < p * n).
Proof.
nzord_induct p.
-order.
-intros p Hp _ n m Hp'. apply lt_succ_l in Hp'. order.
-intros p Hp IH n m _. apply le_succ_l in Hp.
-le_elim Hp.
-assert (LR : forall n m, n < m -> p * m < p * n).
- intros n1 m1 H. apply (le_lt_add_lt n1 m1).
- now apply lt_le_incl. rewrite <- 2 mul_succ_l. now rewrite <- IH.
-split; intros H.
-now apply LR.
-destruct (lt_trichotomy n m) as [LT|[EQ|GT]]; trivial.
-rewrite EQ in H. order.
-apply LR in GT. order.
-rewrite (mul_lt_pred p (S p)), Hp; now nzsimpl.
+- order.
+- intros p Hp _ n m Hp'. apply lt_succ_l in Hp'. order.
+- intros p Hp IH n m _. apply le_succ_l in Hp.
+ le_elim Hp.
+ + assert (LR : forall n m, n < m -> p * m < p * n).
+ * intros n1 m1 H. apply (le_lt_add_lt n1 m1).
+ -- now apply lt_le_incl.
+ -- rewrite <- 2 mul_succ_l. now rewrite <- IH.
+ * split; intros H.
+ -- now apply LR.
+ -- destruct (lt_trichotomy n m) as [LT|[EQ|GT]]; trivial.
+ ++ rewrite EQ in H. order.
+ ++ apply LR in GT. order.
+ + rewrite (mul_lt_pred p (S p)), Hp; now nzsimpl.
Qed.
Theorem mul_lt_mono_neg_r : forall p n m, p < 0 -> (n < m <-> m * p < n * p).
@@ -71,17 +72,17 @@ Qed.
Theorem mul_le_mono_nonneg_l : forall n m p, 0 <= p -> n <= m -> p * n <= p * m.
Proof.
intros n m p H1 H2. le_elim H1.
-le_elim H2. apply lt_le_incl. now apply mul_lt_mono_pos_l.
-apply eq_le_incl; now rewrite H2.
-apply eq_le_incl; rewrite <- H1; now do 2 rewrite mul_0_l.
+- le_elim H2. + apply lt_le_incl. now apply mul_lt_mono_pos_l.
+ + apply eq_le_incl; now rewrite H2.
+- apply eq_le_incl; rewrite <- H1; now do 2 rewrite mul_0_l.
Qed.
Theorem mul_le_mono_nonpos_l : forall n m p, p <= 0 -> n <= m -> p * m <= p * n.
Proof.
intros n m p H1 H2. le_elim H1.
-le_elim H2. apply lt_le_incl. now apply mul_lt_mono_neg_l.
-apply eq_le_incl; now rewrite H2.
-apply eq_le_incl; rewrite H1; now do 2 rewrite mul_0_l.
+- le_elim H2. + apply lt_le_incl. now apply mul_lt_mono_neg_l.
+ + apply eq_le_incl; now rewrite H2.
+- apply eq_le_incl; rewrite H1; now do 2 rewrite mul_0_l.
Qed.
Theorem mul_le_mono_nonneg_r : forall n m p, 0 <= p -> n <= m -> n * p <= m * p.
@@ -101,10 +102,10 @@ Proof.
intros n m p Hp; split; intro H; [|now f_equiv].
apply lt_gt_cases in Hp; destruct Hp as [Hp|Hp];
destruct (lt_trichotomy n m) as [LT|[EQ|GT]]; trivial.
-apply (mul_lt_mono_neg_l p) in LT; order.
-apply (mul_lt_mono_neg_l p) in GT; order.
-apply (mul_lt_mono_pos_l p) in LT; order.
-apply (mul_lt_mono_pos_l p) in GT; order.
+- apply (mul_lt_mono_neg_l p) in LT; order.
+- apply (mul_lt_mono_neg_l p) in GT; order.
+- apply (mul_lt_mono_pos_l p) in LT; order.
+- apply (mul_lt_mono_pos_l p) in GT; order.
Qed.
Theorem mul_cancel_r : forall n m p, p ~= 0 -> (n * p == m * p <-> n == m).
@@ -155,8 +156,8 @@ Theorem mul_lt_mono_nonneg :
Proof.
intros n m p q H1 H2 H3 H4.
apply le_lt_trans with (m * p).
-apply mul_le_mono_nonneg_r; [assumption | now apply lt_le_incl].
-apply -> mul_lt_mono_pos_l; [assumption | now apply le_lt_trans with n].
+- apply mul_le_mono_nonneg_r; [assumption | now apply lt_le_incl].
+- apply -> mul_lt_mono_pos_l; [assumption | now apply le_lt_trans with n].
Qed.
(* There are still many variants of the theorem above. One can assume 0 < n
@@ -167,10 +168,10 @@ Theorem mul_le_mono_nonneg :
Proof.
intros n m p q H1 H2 H3 H4.
le_elim H2; le_elim H4.
-apply lt_le_incl; now apply mul_lt_mono_nonneg.
-rewrite <- H4; apply mul_le_mono_nonneg_r; [assumption | now apply lt_le_incl].
-rewrite <- H2; apply mul_le_mono_nonneg_l; [assumption | now apply lt_le_incl].
-rewrite H2; rewrite H4; now apply eq_le_incl.
+- apply lt_le_incl; now apply mul_lt_mono_nonneg.
+- rewrite <- H4; apply mul_le_mono_nonneg_r; [assumption | now apply lt_le_incl].
+- rewrite <- H2; apply mul_le_mono_nonneg_l; [assumption | now apply lt_le_incl].
+- rewrite H2; rewrite H4; now apply eq_le_incl.
Qed.
Theorem mul_pos_pos : forall n m, 0 < n -> 0 < m -> 0 < n * m.
@@ -225,29 +226,29 @@ Qed.
Theorem lt_1_mul_pos : forall n m, 1 < n -> 0 < m -> 1 < n * m.
Proof.
intros n m H1 H2. apply (mul_lt_mono_pos_r m) in H1.
-rewrite mul_1_l in H1. now apply lt_1_l with m.
-assumption.
+- rewrite mul_1_l in H1. now apply lt_1_l with m.
+- assumption.
Qed.
Theorem eq_mul_0 : forall n m, n * m == 0 <-> n == 0 \/ m == 0.
Proof.
intros n m; split.
-intro H; destruct (lt_trichotomy n 0) as [H1 | [H1 | H1]];
-destruct (lt_trichotomy m 0) as [H2 | [H2 | H2]];
-try (now right); try (now left).
-exfalso; now apply (lt_neq 0 (n * m)); [apply mul_neg_neg |].
-exfalso; now apply (lt_neq (n * m) 0); [apply mul_neg_pos |].
-exfalso; now apply (lt_neq (n * m) 0); [apply mul_pos_neg |].
-exfalso; now apply (lt_neq 0 (n * m)); [apply mul_pos_pos |].
-intros [H | H]. now rewrite H, mul_0_l. now rewrite H, mul_0_r.
+- intro H; destruct (lt_trichotomy n 0) as [H1 | [H1 | H1]];
+ destruct (lt_trichotomy m 0) as [H2 | [H2 | H2]];
+ try (now right); try (now left).
+ + exfalso; now apply (lt_neq 0 (n * m)); [apply mul_neg_neg |].
+ + exfalso; now apply (lt_neq (n * m) 0); [apply mul_neg_pos |].
+ + exfalso; now apply (lt_neq (n * m) 0); [apply mul_pos_neg |].
+ + exfalso; now apply (lt_neq 0 (n * m)); [apply mul_pos_pos |].
+- intros [H | H]. + now rewrite H, mul_0_l. + now rewrite H, mul_0_r.
Qed.
Theorem neq_mul_0 : forall n m, n ~= 0 /\ m ~= 0 <-> n * m ~= 0.
Proof.
intros n m; split; intro H.
-intro H1; apply eq_mul_0 in H1. tauto.
-split; intro H1; rewrite H1 in H;
-(rewrite mul_0_l in H || rewrite mul_0_r in H); now apply H.
+- intro H1; apply eq_mul_0 in H1. tauto.
+- split; intro H1; rewrite H1 in H;
+ (rewrite mul_0_l in H || rewrite mul_0_r in H); now apply H.
Qed.
Theorem eq_square_0 : forall n, n * n == 0 <-> n == 0.
@@ -258,13 +259,13 @@ Qed.
Theorem eq_mul_0_l : forall n m, n * m == 0 -> m ~= 0 -> n == 0.
Proof.
intros n m H1 H2. apply eq_mul_0 in H1. destruct H1 as [H1 | H1].
-assumption. false_hyp H1 H2.
+- assumption. - false_hyp H1 H2.
Qed.
Theorem eq_mul_0_r : forall n m, n * m == 0 -> n ~= 0 -> m == 0.
Proof.
intros n m H1 H2; apply eq_mul_0 in H1. destruct H1 as [H1 | H1].
-false_hyp H1 H2. assumption.
+- false_hyp H1 H2. - assumption.
Qed.
(** Some alternative names: *)
@@ -276,16 +277,16 @@ Definition mul_eq_0_r := eq_mul_0_r.
Theorem lt_0_mul n m : 0 < n * m <-> (0 < n /\ 0 < m) \/ (m < 0 /\ n < 0).
Proof.
split; [intro H | intros [[H1 H2] | [H1 H2]]].
-destruct (lt_trichotomy n 0) as [H1 | [H1 | H1]];
-[| rewrite H1 in H; rewrite mul_0_l in H; false_hyp H lt_irrefl |];
-(destruct (lt_trichotomy m 0) as [H2 | [H2 | H2]];
-[| rewrite H2 in H; rewrite mul_0_r in H; false_hyp H lt_irrefl |]);
-try (left; now split); try (right; now split).
-assert (H3 : n * m < 0) by now apply mul_neg_pos.
-exfalso; now apply (lt_asymm (n * m) 0).
-assert (H3 : n * m < 0) by now apply mul_pos_neg.
-exfalso; now apply (lt_asymm (n * m) 0).
-now apply mul_pos_pos. now apply mul_neg_neg.
+- destruct (lt_trichotomy n 0) as [H1 | [H1 | H1]];
+ [| rewrite H1 in H; rewrite mul_0_l in H; false_hyp H lt_irrefl |];
+ (destruct (lt_trichotomy m 0) as [H2 | [H2 | H2]];
+ [| rewrite H2 in H; rewrite mul_0_r in H; false_hyp H lt_irrefl |]);
+ try (left; now split); try (right; now split).
+ + assert (H3 : n * m < 0) by now apply mul_neg_pos.
+ exfalso; now apply (lt_asymm (n * m) 0).
+ + assert (H3 : n * m < 0) by now apply mul_pos_neg.
+ exfalso; now apply (lt_asymm (n * m) 0).
+- now apply mul_pos_pos. - now apply mul_neg_neg.
Qed.
Theorem square_lt_mono_nonneg : forall n m, 0 <= n -> n < m -> n * n < m * m.
@@ -304,38 +305,38 @@ other variable *)
Theorem square_lt_simpl_nonneg : forall n m, 0 <= m -> n * n < m * m -> n < m.
Proof.
intros n m H1 H2. destruct (lt_ge_cases n 0).
-now apply lt_le_trans with 0.
-destruct (lt_ge_cases n m) as [LT|LE]; trivial.
-apply square_le_mono_nonneg in LE; order.
+- now apply lt_le_trans with 0.
+- destruct (lt_ge_cases n m) as [LT|LE]; trivial.
+ apply square_le_mono_nonneg in LE; order.
Qed.
Theorem square_le_simpl_nonneg : forall n m, 0 <= m -> n * n <= m * m -> n <= m.
Proof.
intros n m H1 H2. destruct (lt_ge_cases n 0).
-apply lt_le_incl; now apply lt_le_trans with 0.
-destruct (le_gt_cases n m) as [LE|LT]; trivial.
-apply square_lt_mono_nonneg in LT; order.
+- apply lt_le_incl; now apply lt_le_trans with 0.
+- destruct (le_gt_cases n m) as [LE|LT]; trivial.
+ apply square_lt_mono_nonneg in LT; order.
Qed.
Theorem mul_2_mono_l : forall n m, n < m -> 1 + 2 * n < 2 * m.
Proof.
intros n m. rewrite <- le_succ_l, (mul_le_mono_pos_l (S n) m two).
-rewrite two_succ. nzsimpl. now rewrite le_succ_l.
-order'.
+- rewrite two_succ. nzsimpl. now rewrite le_succ_l.
+- order'.
Qed.
Lemma add_le_mul : forall a b, 1<a -> 1<b -> a+b <= a*b.
Proof.
assert (AUX : forall a b, 0<a -> 0<b -> (S a)+(S b) <= (S a)*(S b)).
- intros a b Ha Hb.
- nzsimpl. rewrite <- succ_le_mono. apply le_succ_l.
- rewrite <- add_assoc, <- (add_0_l (a+b)), (add_comm b).
- apply add_lt_mono_r.
- now apply mul_pos_pos.
- intros a b Ha Hb.
- assert (Ha' := lt_succ_pred 1 a Ha).
- assert (Hb' := lt_succ_pred 1 b Hb).
- rewrite <- Ha', <- Hb'. apply AUX; rewrite succ_lt_mono, <- one_succ; order.
+ - intros a b Ha Hb.
+ nzsimpl. rewrite <- succ_le_mono. apply le_succ_l.
+ rewrite <- add_assoc, <- (add_0_l (a+b)), (add_comm b).
+ apply add_lt_mono_r.
+ now apply mul_pos_pos.
+ - intros a b Ha Hb.
+ assert (Ha' := lt_succ_pred 1 a Ha).
+ assert (Hb' := lt_succ_pred 1 b Hb).
+ rewrite <- Ha', <- Hb'. apply AUX; rewrite succ_lt_mono, <- one_succ; order.
Qed.
(** A few results about squares *)
@@ -343,25 +344,25 @@ Qed.
Lemma square_nonneg : forall a, 0 <= a * a.
Proof.
intros. rewrite <- (mul_0_r a). destruct (le_gt_cases a 0).
- now apply mul_le_mono_nonpos_l.
- apply mul_le_mono_nonneg_l; order.
+ - now apply mul_le_mono_nonpos_l.
+ - apply mul_le_mono_nonneg_l; order.
Qed.
Lemma crossmul_le_addsquare : forall a b, 0<=a -> 0<=b -> b*a+a*b <= a*a+b*b.
Proof.
assert (AUX : forall a b, 0<=a<=b -> b*a+a*b <= a*a+b*b).
- intros a b (Ha,H).
- destruct (le_exists_sub _ _ H) as (d & EQ & Hd).
- rewrite EQ.
- rewrite 2 mul_add_distr_r.
- rewrite !add_assoc. apply add_le_mono_r.
- rewrite add_comm. apply add_le_mono_l.
- apply mul_le_mono_nonneg_l; trivial. order.
- intros a b Ha Hb.
- destruct (le_gt_cases a b).
- apply AUX; split; order.
- rewrite (add_comm (b*a)), (add_comm (a*a)).
- apply AUX; split; order.
+ - intros a b (Ha,H).
+ destruct (le_exists_sub _ _ H) as (d & EQ & Hd).
+ rewrite EQ.
+ rewrite 2 mul_add_distr_r.
+ rewrite !add_assoc. apply add_le_mono_r.
+ rewrite add_comm. apply add_le_mono_l.
+ apply mul_le_mono_nonneg_l; trivial. order.
+ - intros a b Ha Hb.
+ destruct (le_gt_cases a b).
+ + apply AUX; split; order.
+ + rewrite (add_comm (b*a)), (add_comm (a*a)).
+ apply AUX; split; order.
Qed.
Lemma add_square_le : forall a b, 0<=a -> 0<=b ->
diff --git a/theories/Numbers/NatInt/NZOrder.v b/theories/Numbers/NatInt/NZOrder.v
index 60e1123b35..89bc5cfecb 100644
--- a/theories/Numbers/NatInt/NZOrder.v
+++ b/theories/Numbers/NatInt/NZOrder.v
@@ -60,19 +60,19 @@ Qed.
Theorem nle_succ_diag_l : forall n, ~ S n <= n.
Proof.
intros n H; le_elim H.
-false_hyp H nlt_succ_diag_l. false_hyp H neq_succ_diag_l.
++ false_hyp H nlt_succ_diag_l. + false_hyp H neq_succ_diag_l.
Qed.
Theorem le_succ_l : forall n m, S n <= m <-> n < m.
Proof.
intro n; nzinduct m n.
-split; intro H. false_hyp H nle_succ_diag_l. false_hyp H lt_irrefl.
-intro m.
-rewrite (lt_eq_cases (S n) (S m)), !lt_succ_r, (lt_eq_cases n m), succ_inj_wd.
-rewrite or_cancel_r.
-reflexivity.
-intros LE EQ; rewrite EQ in LE; false_hyp LE nle_succ_diag_l.
-intros LT EQ; rewrite EQ in LT; false_hyp LT lt_irrefl.
+- split; intro H. + false_hyp H nle_succ_diag_l. + false_hyp H lt_irrefl.
+- intro m.
+ rewrite (lt_eq_cases (S n) (S m)), !lt_succ_r, (lt_eq_cases n m), succ_inj_wd.
+ rewrite or_cancel_r.
+ + reflexivity.
+ + intros LE EQ; rewrite EQ in LE; false_hyp LE nle_succ_diag_l.
+ + intros LT EQ; rewrite EQ in LT; false_hyp LT lt_irrefl.
Qed.
(** Trichotomy *)
@@ -80,8 +80,8 @@ Qed.
Theorem le_gt_cases : forall n m, n <= m \/ n > m.
Proof.
intros n m; nzinduct n m.
-left; apply le_refl.
-intro n. rewrite lt_succ_r, le_succ_l, !lt_eq_cases. intuition.
+- left; apply le_refl.
+- intro n. rewrite lt_succ_r, le_succ_l, !lt_eq_cases. intuition.
Qed.
Theorem lt_trichotomy : forall n m, n < m \/ n == m \/ m < n.
@@ -96,14 +96,14 @@ Notation lt_eq_gt_cases := lt_trichotomy (only parsing).
Theorem lt_asymm : forall n m, n < m -> ~ m < n.
Proof.
intros n m; nzinduct n m.
-intros H; false_hyp H lt_irrefl.
-intro n; split; intros H H1 H2.
-apply lt_succ_r in H2. le_elim H2.
-apply H; auto. apply le_succ_l. now apply lt_le_incl.
-rewrite H2 in H1. false_hyp H1 nlt_succ_diag_l.
-apply le_succ_l in H1. le_elim H1.
-apply H; auto. rewrite lt_succ_r. now apply lt_le_incl.
-rewrite <- H1 in H2. false_hyp H2 nlt_succ_diag_l.
+- intros H; false_hyp H lt_irrefl.
+- intro n; split; intros H H1 H2.
+ + apply lt_succ_r in H2. le_elim H2.
+ * apply H; auto. apply le_succ_l. now apply lt_le_incl.
+ * rewrite H2 in H1. false_hyp H1 nlt_succ_diag_l.
+ + apply le_succ_l in H1. le_elim H1.
+ * apply H; auto. rewrite lt_succ_r. now apply lt_le_incl.
+ * rewrite <- H1 in H2. false_hyp H2 nlt_succ_diag_l.
Qed.
Notation lt_ngt := lt_asymm (only parsing).
@@ -111,13 +111,15 @@ Notation lt_ngt := lt_asymm (only parsing).
Theorem lt_trans : forall n m p, n < m -> m < p -> n < p.
Proof.
intros n m p; nzinduct p m.
-intros _ H; false_hyp H lt_irrefl.
-intro p. rewrite 2 lt_succ_r.
-split; intros H H1 H2.
-apply lt_le_incl; le_elim H2; [now apply H | now rewrite H2 in H1].
-assert (n <= p) as H3 by (auto using lt_le_incl).
-le_elim H3. assumption. rewrite <- H3 in H2.
-elim (lt_asymm n m); auto.
+- intros _ H; false_hyp H lt_irrefl.
+- intro p. rewrite 2 lt_succ_r.
+ split; intros H H1 H2.
+ + apply lt_le_incl; le_elim H2; [now apply H | now rewrite H2 in H1].
+ + assert (n <= p) as H3 by (auto using lt_le_incl).
+ le_elim H3.
+ * assumption.
+ * rewrite <- H3 in H2.
+ elim (lt_asymm n m); auto.
Qed.
Theorem le_trans : forall n m p, n <= m -> m <= p -> n <= p.
@@ -130,16 +132,16 @@ Qed.
(** Some type classes about order *)
Instance lt_strorder : StrictOrder lt.
-Proof. split. exact lt_irrefl. exact lt_trans. Qed.
+Proof. split. - exact lt_irrefl. - exact lt_trans. Qed.
Instance le_preorder : PreOrder le.
-Proof. split. exact le_refl. exact le_trans. Qed.
+Proof. split. - exact le_refl. - exact le_trans. Qed.
Instance le_partialorder : PartialOrder _ le.
Proof.
intros x y. compute. split.
-intro EQ; now rewrite EQ.
-rewrite 2 lt_eq_cases. intuition. elim (lt_irrefl x). now transitivity y.
+- intro EQ; now rewrite EQ.
+- rewrite 2 lt_eq_cases. intuition. elim (lt_irrefl x). now transitivity y.
Qed.
(** We know enough now to benefit from the generic [order] tactic. *)
@@ -246,7 +248,7 @@ Qed.
Theorem lt_0_2 : 0 < 2.
Proof.
-transitivity 1. apply lt_0_1. apply lt_1_2.
+ transitivity 1. - apply lt_0_1. - apply lt_1_2.
Qed.
Theorem le_0_2 : 0 <= 2.
@@ -300,9 +302,9 @@ Qed.
Theorem eq_dne : forall n m, ~ ~ n == m <-> n == m.
Proof.
intros n m; split; intro H.
-destruct (eq_decidable n m) as [H1 | H1].
-assumption. false_hyp H1 H.
-intro H1; now apply H1.
+- destruct (eq_decidable n m) as [H1 | H1].
+ + assumption. + false_hyp H1 H.
+- intro H1; now apply H1.
Qed.
Theorem le_ngt : forall n m, n <= m <-> ~ n > m.
@@ -321,8 +323,8 @@ Qed.
Theorem lt_dne : forall n m, ~ ~ n < m <-> n < m.
Proof.
intros n m; split; intro H.
-destruct (lt_decidable n m) as [H1 | H1]; [assumption | false_hyp H1 H].
-intro H1; false_hyp H H1.
+- destruct (lt_decidable n m) as [H1 | H1]; [assumption | false_hyp H1 H].
+- intro H1; false_hyp H H1.
Qed.
Theorem nle_gt : forall n m, ~ n <= m <-> n > m.
@@ -341,8 +343,8 @@ Qed.
Theorem le_dne : forall n m, ~ ~ n <= m <-> n <= m.
Proof.
intros n m; split; intro H.
-destruct (le_decidable n m) as [H1 | H1]; [assumption | false_hyp H1 H].
-intro H1; false_hyp H H1.
+- destruct (le_decidable n m) as [H1 | H1]; [assumption | false_hyp H1 H].
+- intro H1; false_hyp H H1.
Qed.
Theorem nlt_succ_r : forall n m, ~ m < S n <-> n < m.
@@ -361,18 +363,18 @@ Lemma lt_exists_pred_strong :
forall z n m, z < m -> m <= n -> exists k, m == S k /\ z <= k.
Proof.
intro z; nzinduct n z.
-order.
-intro n; split; intros IH m H1 H2.
-apply le_succ_r in H2. destruct H2 as [H2 | H2].
-now apply IH. exists n. now split; [| rewrite <- lt_succ_r; rewrite <- H2].
-apply IH. assumption. now apply le_le_succ_r.
+- order.
+- intro n; split; intros IH m H1 H2.
+ + apply le_succ_r in H2. destruct H2 as [H2 | H2].
+ * now apply IH. * exists n. now split; [| rewrite <- lt_succ_r; rewrite <- H2].
+ + apply IH. * assumption. * now apply le_le_succ_r.
Qed.
Theorem lt_exists_pred :
forall z n, z < n -> exists k, n == S k /\ z <= k.
Proof.
intros z n H; apply lt_exists_pred_strong with (z := z) (n := n).
-assumption. apply le_refl.
+- assumption. - apply le_refl.
Qed.
Lemma lt_succ_pred : forall z n, z < n -> S (P n) == n.
@@ -404,18 +406,19 @@ Let right_step'' := forall n, A' n <-> A' (S n).
Lemma rs_rs' : A z -> right_step -> right_step'.
Proof.
intros Az RS n H1 H2.
-le_elim H1. apply lt_exists_pred in H1. destruct H1 as [k [H3 H4]].
-rewrite H3. apply RS; trivial. apply H2; trivial.
-rewrite H3; apply lt_succ_diag_r.
-rewrite <- H1; apply Az.
+le_elim H1.
+- apply lt_exists_pred in H1. destruct H1 as [k [H3 H4]].
+ rewrite H3. apply RS; trivial. apply H2; trivial.
+ rewrite H3; apply lt_succ_diag_r.
+- rewrite <- H1; apply Az.
Qed.
Lemma rs'_rs'' : right_step' -> right_step''.
Proof.
intros RS' n; split; intros H1 m H2 H3.
-apply lt_succ_r in H3; le_elim H3;
-[now apply H1 | rewrite H3 in *; now apply RS'].
-apply H1; [assumption | now apply lt_lt_succ_r].
+- apply lt_succ_r in H3; le_elim H3;
+ [now apply H1 | rewrite H3 in *; now apply RS'].
+- apply H1; [assumption | now apply lt_lt_succ_r].
Qed.
Lemma rbase : A' z.
@@ -444,10 +447,12 @@ Theorem right_induction' :
Proof.
intros L R n.
destruct (lt_trichotomy n z) as [H | [H | H]].
-apply L; now apply lt_le_incl.
-apply L; now apply eq_le_incl.
-apply right_induction. apply L; now apply eq_le_incl. assumption.
-now apply lt_le_incl.
+- apply L; now apply lt_le_incl.
+- apply L; now apply eq_le_incl.
+- apply right_induction.
+ + apply L; now apply eq_le_incl.
+ + assumption.
+ + now apply lt_le_incl.
Qed.
Theorem strong_right_induction' :
@@ -455,9 +460,10 @@ Theorem strong_right_induction' :
Proof.
intros L R n.
destruct (lt_trichotomy n z) as [H | [H | H]].
-apply L; now apply lt_le_incl.
-apply L; now apply eq_le_incl.
-apply strong_right_induction. assumption. now apply lt_le_incl.
+- apply L; now apply lt_le_incl.
+- apply L; now apply eq_le_incl.
+- apply strong_right_induction.
+ + assumption. + now apply lt_le_incl.
Qed.
End RightInduction.
@@ -472,17 +478,17 @@ Let left_step'' := forall n, A' n <-> A' (S n).
Lemma ls_ls' : A z -> left_step -> left_step'.
Proof.
intros Az LS n H1 H2. le_elim H1.
-apply LS; trivial. apply H2; [now apply le_succ_l | now apply eq_le_incl].
-rewrite H1; apply Az.
+- apply LS; trivial. apply H2; [now apply le_succ_l | now apply eq_le_incl].
+- rewrite H1; apply Az.
Qed.
Lemma ls'_ls'' : left_step' -> left_step''.
Proof.
intros LS' n; split; intros H1 m H2 H3.
-apply le_succ_l in H3. apply lt_le_incl in H3. now apply H1.
-le_elim H3.
-apply le_succ_l in H3. now apply H1.
-rewrite <- H3 in *; now apply LS'.
+- apply le_succ_l in H3. apply lt_le_incl in H3. now apply H1.
+- le_elim H3.
+ + apply le_succ_l in H3. now apply H1.
+ + rewrite <- H3 in *; now apply LS'.
Qed.
Lemma lbase : A' (S z).
@@ -512,10 +518,12 @@ Theorem left_induction' :
Proof.
intros R L n.
destruct (lt_trichotomy n z) as [H | [H | H]].
-apply left_induction. apply R. now apply eq_le_incl. assumption.
-now apply lt_le_incl.
-rewrite H; apply R; now apply eq_le_incl.
-apply R; now apply lt_le_incl.
+- apply left_induction.
+ + apply R. now apply eq_le_incl.
+ + assumption.
+ + now apply lt_le_incl.
+- rewrite H; apply R; now apply eq_le_incl.
+- apply R; now apply lt_le_incl.
Qed.
Theorem strong_left_induction' :
@@ -523,9 +531,9 @@ Theorem strong_left_induction' :
Proof.
intros R L n.
destruct (lt_trichotomy n z) as [H | [H | H]].
-apply strong_left_induction; auto. now apply lt_le_incl.
-rewrite H; apply R; now apply eq_le_incl.
-apply R; now apply lt_le_incl.
+- apply strong_left_induction; auto. now apply lt_le_incl.
+- rewrite H; apply R; now apply eq_le_incl.
+- apply R; now apply lt_le_incl.
Qed.
End LeftInduction.
@@ -538,9 +546,9 @@ Theorem order_induction :
Proof.
intros Az RS LS n.
destruct (lt_trichotomy n z) as [H | [H | H]].
-now apply left_induction; [| | apply lt_le_incl].
-now rewrite H.
-now apply right_induction; [| | apply lt_le_incl].
+- now apply left_induction; [| | apply lt_le_incl].
+- now rewrite H.
+- now apply right_induction; [| | apply lt_le_incl].
Qed.
Theorem order_induction' :
@@ -622,21 +630,24 @@ Theorem lt_wf : well_founded Rlt.
Proof.
unfold well_founded.
apply strong_right_induction' with (z := z).
-auto with typeclass_instances.
-intros n H; constructor; intros y [H1 H2].
-apply nle_gt in H2. elim H2. now apply le_trans with z.
-intros n H1 H2; constructor; intros m [H3 H4]. now apply H2.
+- auto with typeclass_instances.
+- intros n H; constructor; intros y [H1 H2].
+ apply nle_gt in H2. elim H2. now apply le_trans with z.
+- intros n H1 H2; constructor; intros m [H3 H4]. now apply H2.
Qed.
Theorem gt_wf : well_founded Rgt.
Proof.
unfold well_founded.
apply strong_left_induction' with (z := z).
-auto with typeclass_instances.
-intros n H; constructor; intros y [H1 H2].
-apply nle_gt in H2. elim H2. now apply le_lt_trans with n.
-intros n H1 H2; constructor; intros m [H3 H4].
-apply H2. assumption. now apply le_succ_l.
+- auto with typeclass_instances.
+- intros n H; constructor; intros y [H1 H2].
+ apply nle_gt in H2.
+ + elim H2.
+ + now apply le_lt_trans with n.
+- intros n H1 H2; constructor; intros m [H3 H4].
+ apply H2.
+ + assumption. + now apply le_succ_l.
Qed.
End WF.
diff --git a/theories/Numbers/NatInt/NZParity.v b/theories/Numbers/NatInt/NZParity.v
index 93d99f08f5..84b8a96e64 100644
--- a/theories/Numbers/NatInt/NZParity.v
+++ b/theories/Numbers/NatInt/NZParity.v
@@ -48,20 +48,20 @@ Qed.
Lemma Even_or_Odd : forall x, Even x \/ Odd x.
Proof.
nzinduct x.
- left. exists 0. now nzsimpl.
- intros x.
- split; intros [(y,H)|(y,H)].
- right. exists y. rewrite H. now nzsimpl.
- left. exists (S y). rewrite H. now nzsimpl'.
- right.
- assert (LT : exists z, z<y).
- destruct (lt_ge_cases 0 y) as [LT|GT]; [now exists 0 | exists x].
- rewrite <- le_succ_l, H. nzsimpl'.
- rewrite <- (add_0_r y) at 3. now apply add_le_mono_l.
- destruct LT as (z,LT).
- destruct (lt_exists_pred z y LT) as (y' & Hy' & _).
- exists y'. rewrite <- succ_inj_wd, H, Hy'. now nzsimpl'.
- left. exists y. rewrite <- succ_inj_wd. rewrite H. now nzsimpl.
+ - left. exists 0. now nzsimpl.
+ - intros x.
+ split; intros [(y,H)|(y,H)].
+ + right. exists y. rewrite H. now nzsimpl.
+ + left. exists (S y). rewrite H. now nzsimpl'.
+ + right.
+ assert (LT : exists z, z<y).
+ * destruct (lt_ge_cases 0 y) as [LT|GT]; [now exists 0 | exists x].
+ rewrite <- le_succ_l, H. nzsimpl'.
+ rewrite <- (add_0_r y) at 3. now apply add_le_mono_l.
+ * destruct LT as (z,LT).
+ destruct (lt_exists_pred z y LT) as (y' & Hy' & _).
+ exists y'. rewrite <- succ_inj_wd, H, Hy'. now nzsimpl'.
+ + left. exists y. rewrite <- succ_inj_wd. rewrite H. now nzsimpl.
Qed.
Lemma double_below : forall n m, n<=m -> 2*n < 2*m+1.
@@ -80,16 +80,16 @@ Lemma Even_Odd_False : forall x, Even x -> Odd x -> False.
Proof.
intros x (y,E) (z,O). rewrite O in E; clear O.
destruct (le_gt_cases y z) as [LE|GT].
-generalize (double_below _ _ LE); order.
-generalize (double_above _ _ GT); order.
+- generalize (double_below _ _ LE); order.
+- generalize (double_above _ _ GT); order.
Qed.
Lemma orb_even_odd : forall n, orb (even n) (odd n) = true.
Proof.
intros.
destruct (Even_or_Odd n) as [H|H].
- rewrite <- even_spec in H. now rewrite H.
- rewrite <- odd_spec in H. now rewrite H, orb_true_r.
+ - rewrite <- even_spec in H. now rewrite H.
+ - rewrite <- odd_spec in H. now rewrite H, orb_true_r.
Qed.
Lemma negb_odd : forall n, negb (odd n) = even n.
@@ -142,8 +142,8 @@ Qed.
Lemma Odd_succ : forall n, Odd (S n) <-> Even n.
Proof.
split; intros (m,H).
- exists m. apply succ_inj. now rewrite add_1_r in H.
- exists m. rewrite add_1_r. now f_equiv.
+ - exists m. apply succ_inj. now rewrite add_1_r in H.
+ - exists m. rewrite add_1_r. now f_equiv.
Qed.
Lemma odd_succ : forall n, odd (S n) = even n.
@@ -192,10 +192,10 @@ Proof.
case_eq (even n); case_eq (even m);
rewrite <- ?negb_true_iff, ?negb_even, ?odd_spec, ?even_spec;
intros (m',Hm) (n',Hn).
- exists (n'+m'). now rewrite mul_add_distr_l, Hn, Hm.
- exists (n'+m'). now rewrite mul_add_distr_l, Hn, Hm, add_assoc.
- exists (n'+m'). now rewrite mul_add_distr_l, Hn, Hm, add_shuffle0.
- exists (n'+m'+1). rewrite Hm,Hn. nzsimpl'. now rewrite add_shuffle1.
+ - exists (n'+m'). now rewrite mul_add_distr_l, Hn, Hm.
+ - exists (n'+m'). now rewrite mul_add_distr_l, Hn, Hm, add_assoc.
+ - exists (n'+m'). now rewrite mul_add_distr_l, Hn, Hm, add_shuffle0.
+ - exists (n'+m'+1). rewrite Hm,Hn. nzsimpl'. now rewrite add_shuffle1.
Qed.
Lemma odd_add : forall n m, odd (n+m) = xorb (odd n) (odd m).
@@ -210,14 +210,14 @@ Lemma even_mul : forall n m, even (mul n m) = even n || even m.
Proof.
intros.
case_eq (even n); simpl; rewrite ?even_spec.
- intros (n',Hn). exists (n'*m). now rewrite Hn, mul_assoc.
- case_eq (even m); simpl; rewrite ?even_spec.
- intros (m',Hm). exists (n*m'). now rewrite Hm, !mul_assoc, (mul_comm 2).
- (* odd / odd *)
- rewrite <- !negb_true_iff, !negb_even, !odd_spec.
- intros (m',Hm) (n',Hn). exists (n'*2*m' +n'+m').
- rewrite Hn,Hm, !mul_add_distr_l, !mul_add_distr_r, !mul_1_l, !mul_1_r.
- now rewrite add_shuffle1, add_assoc, !mul_assoc.
+ - intros (n',Hn). exists (n'*m). now rewrite Hn, mul_assoc.
+ - case_eq (even m); simpl; rewrite ?even_spec.
+ + intros (m',Hm). exists (n*m'). now rewrite Hm, !mul_assoc, (mul_comm 2).
+ (* odd / odd *)
+ + rewrite <- !negb_true_iff, !negb_even, !odd_spec.
+ intros (m',Hm) (n',Hn). exists (n'*2*m' +n'+m').
+ rewrite Hn,Hm, !mul_add_distr_l, !mul_add_distr_r, !mul_1_l, !mul_1_r.
+ now rewrite add_shuffle1, add_assoc, !mul_assoc.
Qed.
Lemma odd_mul : forall n m, odd (mul n m) = odd n && odd m.
diff --git a/theories/Numbers/NatInt/NZPow.v b/theories/Numbers/NatInt/NZPow.v
index a1310667e1..830540bc66 100644
--- a/theories/Numbers/NatInt/NZPow.v
+++ b/theories/Numbers/NatInt/NZPow.v
@@ -60,8 +60,8 @@ Lemma pow_0_l' : forall a, a~=0 -> 0^a == 0.
Proof.
intros a Ha.
destruct (lt_trichotomy a 0) as [LT|[EQ|GT]]; try order.
- now rewrite pow_neg_r.
- now apply pow_0_l.
+ - now rewrite pow_neg_r.
+ - now apply pow_0_l.
Qed.
Lemma pow_1_r : forall a, a^1 == a.
@@ -71,9 +71,9 @@ Qed.
Lemma pow_1_l : forall a, 0<=a -> 1^a == 1.
Proof.
- apply le_ind; intros. solve_proper.
- now nzsimpl.
- now nzsimpl.
+ apply le_ind; intros. - solve_proper.
+ - now nzsimpl.
+ - now nzsimpl.
Qed.
Hint Rewrite pow_1_r pow_1_l : nz.
@@ -90,12 +90,12 @@ Hint Rewrite pow_2_r : nz.
Lemma pow_eq_0 : forall a b, 0<=b -> a^b == 0 -> a == 0.
Proof.
intros a b Hb. apply le_ind with (4:=Hb).
- solve_proper.
- rewrite pow_0_r. order'.
- clear b Hb. intros b Hb IH.
- rewrite pow_succ_r by trivial.
- intros H. apply eq_mul_0 in H. destruct H; trivial.
- now apply IH.
+ - solve_proper.
+ - rewrite pow_0_r. order'.
+ - clear b Hb. intros b Hb IH.
+ rewrite pow_succ_r by trivial.
+ intros H. apply eq_mul_0 in H. destruct H; trivial.
+ now apply IH.
Qed.
Lemma pow_nonzero : forall a b, a~=0 -> 0<=b -> a^b ~= 0.
@@ -106,13 +106,13 @@ Qed.
Lemma pow_eq_0_iff : forall a b, a^b == 0 <-> b<0 \/ (0<b /\ a==0).
Proof.
intros a b. split.
- intros H.
- destruct (lt_trichotomy b 0) as [Hb|[Hb|Hb]].
- now left.
- rewrite Hb, pow_0_r in H; order'.
- right. split; trivial. apply pow_eq_0 with b; order.
- intros [Hb|[Hb Ha]]. now rewrite pow_neg_r.
- rewrite Ha. apply pow_0_l'. order.
+ - intros H.
+ destruct (lt_trichotomy b 0) as [Hb|[Hb|Hb]].
+ + now left.
+ + rewrite Hb, pow_0_r in H; order'.
+ + right. split; trivial. apply pow_eq_0 with b; order.
+ - intros [Hb|[Hb Ha]]. + now rewrite pow_neg_r.
+ + rewrite Ha. apply pow_0_l'. order.
Qed.
(** Power and addition, multiplication *)
@@ -120,12 +120,12 @@ Qed.
Lemma pow_add_r : forall a b c, 0<=b -> 0<=c ->
a^(b+c) == a^b * a^c.
Proof.
- intros a b c Hb. apply le_ind with (4:=Hb). solve_proper.
- now nzsimpl.
- clear b Hb. intros b Hb IH Hc.
- nzsimpl; trivial.
- rewrite IH; trivial. apply mul_assoc.
- now apply add_nonneg_nonneg.
+ intros a b c Hb. apply le_ind with (4:=Hb). - solve_proper.
+ - now nzsimpl.
+ - clear b Hb. intros b Hb IH Hc.
+ nzsimpl; trivial.
+ + rewrite IH; trivial. apply mul_assoc.
+ + now apply add_nonneg_nonneg.
Qed.
Lemma pow_mul_l : forall a b c,
@@ -133,23 +133,23 @@ Lemma pow_mul_l : forall a b c,
Proof.
intros a b c.
destruct (lt_ge_cases c 0) as [Hc|Hc].
- rewrite !(pow_neg_r _ _ Hc). now nzsimpl.
- apply le_ind with (4:=Hc). solve_proper.
- now nzsimpl.
- clear c Hc. intros c Hc IH.
- nzsimpl; trivial.
- rewrite IH; trivial. apply mul_shuffle1.
+ - rewrite !(pow_neg_r _ _ Hc). now nzsimpl.
+ - apply le_ind with (4:=Hc). + solve_proper.
+ + now nzsimpl.
+ + clear c Hc. intros c Hc IH.
+ nzsimpl; trivial.
+ rewrite IH; trivial. apply mul_shuffle1.
Qed.
Lemma pow_mul_r : forall a b c, 0<=b -> 0<=c ->
a^(b*c) == (a^b)^c.
Proof.
- intros a b c Hb. apply le_ind with (4:=Hb). solve_proper.
- intros. now nzsimpl.
- clear b Hb. intros b Hb IH Hc.
- nzsimpl; trivial.
- rewrite pow_add_r, IH, pow_mul_l; trivial. apply mul_comm.
- now apply mul_nonneg_nonneg.
+ intros a b c Hb. apply le_ind with (4:=Hb). - solve_proper.
+ - intros. now nzsimpl.
+ - clear b Hb. intros b Hb IH Hc.
+ nzsimpl; trivial.
+ rewrite pow_add_r, IH, pow_mul_l; trivial. + apply mul_comm.
+ + now apply mul_nonneg_nonneg.
Qed.
(** Positivity *)
@@ -158,67 +158,67 @@ Lemma pow_nonneg : forall a b, 0<=a -> 0<=a^b.
Proof.
intros a b Ha.
destruct (lt_ge_cases b 0) as [Hb|Hb].
- now rewrite !(pow_neg_r _ _ Hb).
- apply le_ind with (4:=Hb). solve_proper.
- nzsimpl; order'.
- clear b Hb. intros b Hb IH.
- nzsimpl; trivial. now apply mul_nonneg_nonneg.
+ - now rewrite !(pow_neg_r _ _ Hb).
+ - apply le_ind with (4:=Hb). + solve_proper.
+ + nzsimpl; order'.
+ + clear b Hb. intros b Hb IH.
+ nzsimpl; trivial. now apply mul_nonneg_nonneg.
Qed.
Lemma pow_pos_nonneg : forall a b, 0<a -> 0<=b -> 0<a^b.
Proof.
- intros a b Ha Hb. apply le_ind with (4:=Hb). solve_proper.
- nzsimpl; order'.
- clear b Hb. intros b Hb IH.
- nzsimpl; trivial. now apply mul_pos_pos.
+ intros a b Ha Hb. apply le_ind with (4:=Hb). - solve_proper.
+ - nzsimpl; order'.
+ - clear b Hb. intros b Hb IH.
+ nzsimpl; trivial. now apply mul_pos_pos.
Qed.
(** Monotonicity *)
Lemma pow_lt_mono_l : forall a b c, 0<c -> 0<=a<b -> a^c < b^c.
Proof.
- intros a b c Hc. apply lt_ind with (4:=Hc). solve_proper.
- intros (Ha,H). nzsimpl; trivial; order.
- clear c Hc. intros c Hc IH (Ha,H).
- nzsimpl; try order.
- apply mul_lt_mono_nonneg; trivial.
- apply pow_nonneg; try order.
- apply IH. now split.
+ intros a b c Hc. apply lt_ind with (4:=Hc). - solve_proper.
+ - intros (Ha,H). nzsimpl; trivial; order.
+ - clear c Hc. intros c Hc IH (Ha,H).
+ nzsimpl; try order.
+ apply mul_lt_mono_nonneg; trivial.
+ + apply pow_nonneg; try order.
+ + apply IH. now split.
Qed.
Lemma pow_le_mono_l : forall a b c, 0<=a<=b -> a^c <= b^c.
Proof.
intros a b c (Ha,H).
destruct (lt_trichotomy c 0) as [Hc|[Hc|Hc]].
- rewrite !(pow_neg_r _ _ Hc); now nzsimpl.
- rewrite Hc; now nzsimpl.
- apply lt_eq_cases in H. destruct H as [H|H]; [|now rewrite <- H].
- apply lt_le_incl, pow_lt_mono_l; now try split.
+ - rewrite !(pow_neg_r _ _ Hc); now nzsimpl.
+ - rewrite Hc; now nzsimpl.
+ - apply lt_eq_cases in H. destruct H as [H|H]; [|now rewrite <- H].
+ apply lt_le_incl, pow_lt_mono_l; now try split.
Qed.
Lemma pow_gt_1 : forall a b, 1<a -> (0<b <-> 1<a^b).
Proof.
intros a b Ha. split; intros Hb.
- rewrite <- (pow_1_l b) by order.
- apply pow_lt_mono_l; try split; order'.
- destruct (lt_trichotomy b 0) as [H|[H|H]]; trivial.
- rewrite pow_neg_r in Hb; order'.
- rewrite H, pow_0_r in Hb. order.
+ - rewrite <- (pow_1_l b) by order.
+ apply pow_lt_mono_l; try split; order'.
+ - destruct (lt_trichotomy b 0) as [H|[H|H]]; trivial.
+ + rewrite pow_neg_r in Hb; order'.
+ + rewrite H, pow_0_r in Hb. order.
Qed.
Lemma pow_lt_mono_r : forall a b c, 1<a -> 0<=c -> b<c -> a^b < a^c.
Proof.
intros a b c Ha Hc H.
destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite pow_neg_r by trivial. apply pow_pos_nonneg; order'.
- assert (H' : b<=c) by order.
- destruct (le_exists_sub _ _ H') as (d & EQ & Hd).
- rewrite EQ, pow_add_r; trivial. rewrite <- (mul_1_l (a^b)) at 1.
- apply mul_lt_mono_pos_r.
- apply pow_pos_nonneg; order'.
- apply pow_gt_1; trivial.
- apply lt_eq_cases in Hd; destruct Hd as [LT|EQ']; trivial.
- rewrite <- EQ' in *. rewrite add_0_l in EQ. order.
+ - rewrite pow_neg_r by trivial. apply pow_pos_nonneg; order'.
+ - assert (H' : b<=c) by order.
+ destruct (le_exists_sub _ _ H') as (d & EQ & Hd).
+ rewrite EQ, pow_add_r; trivial. rewrite <- (mul_1_l (a^b)) at 1.
+ apply mul_lt_mono_pos_r.
+ + apply pow_pos_nonneg; order'.
+ + apply pow_gt_1; trivial.
+ apply lt_eq_cases in Hd; destruct Hd as [LT|EQ']; trivial.
+ rewrite <- EQ' in *. rewrite add_0_l in EQ. order.
Qed.
(** NB: since 0^0 > 0^1, the following result isn't valid with a=0 *)
@@ -227,20 +227,20 @@ Lemma pow_le_mono_r : forall a b c, 0<a -> b<=c -> a^b <= a^c.
Proof.
intros a b c Ha H.
destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite (pow_neg_r _ _ Hb). apply pow_nonneg; order.
- apply le_succ_l in Ha; rewrite <- one_succ in Ha.
- apply lt_eq_cases in Ha; destruct Ha as [Ha|Ha]; [|rewrite <- Ha].
- apply lt_eq_cases in H; destruct H as [H|H]; [|now rewrite <- H].
- apply lt_le_incl, pow_lt_mono_r; order.
- nzsimpl; order.
+ - rewrite (pow_neg_r _ _ Hb). apply pow_nonneg; order.
+ - apply le_succ_l in Ha; rewrite <- one_succ in Ha.
+ apply lt_eq_cases in Ha; destruct Ha as [Ha|Ha]; [|rewrite <- Ha].
+ + apply lt_eq_cases in H; destruct H as [H|H]; [|now rewrite <- H].
+ apply lt_le_incl, pow_lt_mono_r; order.
+ + nzsimpl; order.
Qed.
Lemma pow_le_mono : forall a b c d, 0<a<=c -> b<=d ->
a^b <= c^d.
Proof.
intros. transitivity (a^d).
- apply pow_le_mono_r; intuition order.
- apply pow_le_mono_l; intuition order.
+ - apply pow_le_mono_r; intuition order.
+ - apply pow_le_mono_l; intuition order.
Qed.
Lemma pow_lt_mono : forall a b c d, 0<a<c -> 0<b<d ->
@@ -249,10 +249,10 @@ Proof.
intros a b c d (Ha,Hac) (Hb,Hbd).
apply le_succ_l in Ha; rewrite <- one_succ in Ha.
apply lt_eq_cases in Ha; destruct Ha as [Ha|Ha]; [|rewrite <- Ha].
- transitivity (a^d).
- apply pow_lt_mono_r; intuition order.
- apply pow_lt_mono_l; try split; order'.
- nzsimpl; try order. apply pow_gt_1; order.
+ - transitivity (a^d).
+ + apply pow_lt_mono_r; intuition order.
+ + apply pow_lt_mono_l; try split; order'.
+ - nzsimpl; try order. apply pow_gt_1; order.
Qed.
(** Injectivity *)
@@ -262,10 +262,10 @@ Lemma pow_inj_l : forall a b c, 0<=a -> 0<=b -> 0<c ->
Proof.
intros a b c Ha Hb Hc EQ.
destruct (lt_trichotomy a b) as [LT|[EQ'|GT]]; trivial.
- assert (a^c < b^c) by (apply pow_lt_mono_l; try split; trivial).
- order.
- assert (b^c < a^c) by (apply pow_lt_mono_l; try split; trivial).
- order.
+ - assert (a^c < b^c) by (apply pow_lt_mono_l; try split; trivial).
+ order.
+ - assert (b^c < a^c) by (apply pow_lt_mono_l; try split; trivial).
+ order.
Qed.
Lemma pow_inj_r : forall a b c, 1<a -> 0<=b -> 0<=c ->
@@ -273,10 +273,10 @@ Lemma pow_inj_r : forall a b c, 1<a -> 0<=b -> 0<=c ->
Proof.
intros a b c Ha Hb Hc EQ.
destruct (lt_trichotomy b c) as [LT|[EQ'|GT]]; trivial.
- assert (a^b < a^c) by (apply pow_lt_mono_r; try split; trivial).
- order.
- assert (a^c < a^b) by (apply pow_lt_mono_r; try split; trivial).
- order.
+ - assert (a^b < a^c) by (apply pow_lt_mono_r; try split; trivial).
+ order.
+ - assert (a^c < a^b) by (apply pow_lt_mono_r; try split; trivial).
+ order.
Qed.
(** Monotonicity results, both ways *)
@@ -286,10 +286,10 @@ Lemma pow_lt_mono_l_iff : forall a b c, 0<=a -> 0<=b -> 0<c ->
Proof.
intros a b c Ha Hb Hc.
split; intro LT.
- apply pow_lt_mono_l; try split; trivial.
- destruct (le_gt_cases b a) as [LE|GT]; trivial.
- assert (b^c <= a^c) by (apply pow_le_mono_l; try split; order).
- order.
+ - apply pow_lt_mono_l; try split; trivial.
+ - destruct (le_gt_cases b a) as [LE|GT]; trivial.
+ assert (b^c <= a^c) by (apply pow_le_mono_l; try split; order).
+ order.
Qed.
Lemma pow_le_mono_l_iff : forall a b c, 0<=a -> 0<=b -> 0<c ->
@@ -297,10 +297,10 @@ Lemma pow_le_mono_l_iff : forall a b c, 0<=a -> 0<=b -> 0<c ->
Proof.
intros a b c Ha Hb Hc.
split; intro LE.
- apply pow_le_mono_l; try split; trivial.
- destruct (le_gt_cases a b) as [LE'|GT]; trivial.
- assert (b^c < a^c) by (apply pow_lt_mono_l; try split; trivial).
- order.
+ - apply pow_le_mono_l; try split; trivial.
+ - destruct (le_gt_cases a b) as [LE'|GT]; trivial.
+ assert (b^c < a^c) by (apply pow_lt_mono_l; try split; trivial).
+ order.
Qed.
Lemma pow_lt_mono_r_iff : forall a b c, 1<a -> 0<=c ->
@@ -308,10 +308,10 @@ Lemma pow_lt_mono_r_iff : forall a b c, 1<a -> 0<=c ->
Proof.
intros a b c Ha Hc.
split; intro LT.
- now apply pow_lt_mono_r.
- destruct (le_gt_cases c b) as [LE|GT]; trivial.
- assert (a^c <= a^b) by (apply pow_le_mono_r; order').
- order.
+ - now apply pow_lt_mono_r.
+ - destruct (le_gt_cases c b) as [LE|GT]; trivial.
+ assert (a^c <= a^b) by (apply pow_le_mono_r; order').
+ order.
Qed.
Lemma pow_le_mono_r_iff : forall a b c, 1<a -> 0<=c ->
@@ -319,26 +319,26 @@ Lemma pow_le_mono_r_iff : forall a b c, 1<a -> 0<=c ->
Proof.
intros a b c Ha Hc.
split; intro LE.
- apply pow_le_mono_r; order'.
- destruct (le_gt_cases b c) as [LE'|GT]; trivial.
- assert (a^c < a^b) by (apply pow_lt_mono_r; order').
- order.
+ - apply pow_le_mono_r; order'.
+ - destruct (le_gt_cases b c) as [LE'|GT]; trivial.
+ assert (a^c < a^b) by (apply pow_lt_mono_r; order').
+ order.
Qed.
(** For any a>1, the a^x function is above the identity function *)
Lemma pow_gt_lin_r : forall a b, 1<a -> 0<=b -> b < a^b.
Proof.
- intros a b Ha Hb. apply le_ind with (4:=Hb). solve_proper.
- nzsimpl. order'.
- clear b Hb. intros b Hb IH. nzsimpl; trivial.
- rewrite <- !le_succ_l in *. rewrite <- two_succ in Ha.
- transitivity (2*(S b)).
- nzsimpl'. rewrite <- 2 succ_le_mono.
- rewrite <- (add_0_l b) at 1. apply add_le_mono; order.
- apply mul_le_mono_nonneg; trivial.
- order'.
- now apply lt_le_incl, lt_succ_r.
+ intros a b Ha Hb. apply le_ind with (4:=Hb). - solve_proper.
+ - nzsimpl. order'.
+ - clear b Hb. intros b Hb IH. nzsimpl; trivial.
+ rewrite <- !le_succ_l in *. rewrite <- two_succ in Ha.
+ transitivity (2*(S b)).
+ + nzsimpl'. rewrite <- 2 succ_le_mono.
+ rewrite <- (add_0_l b) at 1. apply add_le_mono; order.
+ + apply mul_le_mono_nonneg; trivial.
+ * order'.
+ * now apply lt_le_incl, lt_succ_r.
Qed.
(** Someday, we should say something about the full Newton formula.
@@ -349,22 +349,22 @@ Qed.
Lemma pow_add_lower : forall a b c, 0<=a -> 0<=b -> 0<c ->
a^c + b^c <= (a+b)^c.
Proof.
- intros a b c Ha Hb Hc. apply lt_ind with (4:=Hc). solve_proper.
- nzsimpl; order.
- clear c Hc. intros c Hc IH.
- assert (0<=c) by order'.
- nzsimpl; trivial.
- transitivity ((a+b)*(a^c + b^c)).
- rewrite mul_add_distr_r, !mul_add_distr_l.
- apply add_le_mono.
- rewrite <- add_0_r at 1. apply add_le_mono_l.
- apply mul_nonneg_nonneg; trivial.
- apply pow_nonneg; trivial.
- rewrite <- add_0_l at 1. apply add_le_mono_r.
- apply mul_nonneg_nonneg; trivial.
- apply pow_nonneg; trivial.
- apply mul_le_mono_nonneg_l; trivial.
- now apply add_nonneg_nonneg.
+ intros a b c Ha Hb Hc. apply lt_ind with (4:=Hc). - solve_proper.
+ - nzsimpl; order.
+ - clear c Hc. intros c Hc IH.
+ assert (0<=c) by order'.
+ nzsimpl; trivial.
+ transitivity ((a+b)*(a^c + b^c)).
+ + rewrite mul_add_distr_r, !mul_add_distr_l.
+ apply add_le_mono.
+ * rewrite <- add_0_r at 1. apply add_le_mono_l.
+ apply mul_nonneg_nonneg; trivial.
+ apply pow_nonneg; trivial.
+ * rewrite <- add_0_l at 1. apply add_le_mono_r.
+ apply mul_nonneg_nonneg; trivial.
+ apply pow_nonneg; trivial.
+ + apply mul_le_mono_nonneg_l; trivial.
+ now apply add_nonneg_nonneg.
Qed.
(** This upper bound can also be seen as a convexity proof for x^c :
@@ -377,37 +377,37 @@ Proof.
assert (aux : forall a b c, 0<=a<=b -> 0<c ->
(a + b) * (a ^ c + b ^ c) <= 2 * (a * a ^ c + b * b ^ c)).
(* begin *)
- intros a b c (Ha,H) Hc.
- rewrite !mul_add_distr_l, !mul_add_distr_r. nzsimpl'.
- rewrite <- !add_assoc. apply add_le_mono_l.
- rewrite !add_assoc. apply add_le_mono_r.
- destruct (le_exists_sub _ _ H) as (d & EQ & Hd).
- rewrite EQ.
- rewrite 2 mul_add_distr_r.
- rewrite !add_assoc. apply add_le_mono_r.
- rewrite add_comm. apply add_le_mono_l.
- apply mul_le_mono_nonneg_l; trivial.
- apply pow_le_mono_l; try split; order.
- (* end *)
- intros a b c Ha Hb Hc. apply lt_ind with (4:=Hc). solve_proper.
- nzsimpl; order.
- clear c Hc. intros c Hc IH.
- assert (0<=c) by order.
- nzsimpl; trivial.
- transitivity ((a+b)*(2^(pred c) * (a^c + b^c))).
- apply mul_le_mono_nonneg_l; trivial.
- now apply add_nonneg_nonneg.
- rewrite mul_assoc. rewrite (mul_comm (a+b)).
- assert (EQ : S (P c) == c) by (apply lt_succ_pred with 0; order').
- assert (LE : 0 <= P c) by (now rewrite succ_le_mono, EQ, le_succ_l).
- assert (EQ' : 2^c == 2^(P c) * 2) by (rewrite <- EQ at 1; nzsimpl'; order).
- rewrite EQ', <- !mul_assoc.
- apply mul_le_mono_nonneg_l.
- apply pow_nonneg; order'.
- destruct (le_gt_cases a b).
- apply aux; try split; order'.
- rewrite (add_comm a), (add_comm (a^c)), (add_comm (a*a^c)).
- apply aux; try split; order'.
+ - intros a b c (Ha,H) Hc.
+ rewrite !mul_add_distr_l, !mul_add_distr_r. nzsimpl'.
+ rewrite <- !add_assoc. apply add_le_mono_l.
+ rewrite !add_assoc. apply add_le_mono_r.
+ destruct (le_exists_sub _ _ H) as (d & EQ & Hd).
+ rewrite EQ.
+ rewrite 2 mul_add_distr_r.
+ rewrite !add_assoc. apply add_le_mono_r.
+ rewrite add_comm. apply add_le_mono_l.
+ apply mul_le_mono_nonneg_l; trivial.
+ apply pow_le_mono_l; try split; order.
+ (* end *)
+ - intros a b c Ha Hb Hc. apply lt_ind with (4:=Hc). + solve_proper.
+ + nzsimpl; order.
+ + clear c Hc. intros c Hc IH.
+ assert (0<=c) by order.
+ nzsimpl; trivial.
+ transitivity ((a+b)*(2^(pred c) * (a^c + b^c))).
+ * apply mul_le_mono_nonneg_l; trivial.
+ now apply add_nonneg_nonneg.
+ * rewrite mul_assoc. rewrite (mul_comm (a+b)).
+ assert (EQ : S (P c) == c) by (apply lt_succ_pred with 0; order').
+ assert (LE : 0 <= P c) by (now rewrite succ_le_mono, EQ, le_succ_l).
+ assert (EQ' : 2^c == 2^(P c) * 2) by (rewrite <- EQ at 1; nzsimpl'; order).
+ rewrite EQ', <- !mul_assoc.
+ apply mul_le_mono_nonneg_l.
+ -- apply pow_nonneg; order'.
+ -- destruct (le_gt_cases a b).
+ ++ apply aux; try split; order'.
+ ++ rewrite (add_comm a), (add_comm (a^c)), (add_comm (a*a^c)).
+ apply aux; try split; order'.
Qed.
End NZPowProp.
diff --git a/theories/Numbers/NatInt/NZSqrt.v b/theories/Numbers/NatInt/NZSqrt.v
index c2d2c4ae19..85ed71b8a4 100644
--- a/theories/Numbers/NatInt/NZSqrt.v
+++ b/theories/Numbers/NatInt/NZSqrt.v
@@ -49,18 +49,18 @@ Proof.
intros b LT.
destruct (le_gt_cases 0 b) as [Hb|Hb]; trivial. exfalso.
assert ((S b)² < b²).
- rewrite mul_succ_l, <- (add_0_r b²).
- apply add_lt_le_mono.
- apply mul_lt_mono_neg_l; trivial. apply lt_succ_diag_r.
- now apply le_succ_l.
- order.
+ - rewrite mul_succ_l, <- (add_0_r b²).
+ apply add_lt_le_mono.
+ + apply mul_lt_mono_neg_l; trivial. apply lt_succ_diag_r.
+ + now apply le_succ_l.
+ - order.
Qed.
Lemma sqrt_nonneg : forall a, 0<=√a.
Proof.
intros. destruct (lt_ge_cases a 0) as [Ha|Ha].
- now rewrite (sqrt_neg _ Ha).
- apply sqrt_spec_nonneg. destruct (sqrt_spec a Ha). order.
+ - now rewrite (sqrt_neg _ Ha).
+ - apply sqrt_spec_nonneg. destruct (sqrt_spec a Ha). order.
Qed.
(** The spec of sqrt indeed determines it *)
@@ -73,12 +73,12 @@ Proof.
assert (Ha': 0<=√a) by now apply sqrt_nonneg.
destruct (sqrt_spec a Ha) as (LEa,LTa).
assert (b <= √a).
- apply lt_succ_r, square_lt_simpl_nonneg; [|order].
- now apply lt_le_incl, lt_succ_r.
- assert (√a <= b).
- apply lt_succ_r, square_lt_simpl_nonneg; [|order].
- now apply lt_le_incl, lt_succ_r.
- order.
+ - apply lt_succ_r, square_lt_simpl_nonneg; [|order].
+ now apply lt_le_incl, lt_succ_r.
+ - assert (√a <= b).
+ + apply lt_succ_r, square_lt_simpl_nonneg; [|order].
+ now apply lt_le_incl, lt_succ_r.
+ + order.
Qed.
(** Hence sqrt is a morphism *)
@@ -87,9 +87,9 @@ Instance sqrt_wd : Proper (eq==>eq) sqrt.
Proof.
intros x x' Hx.
destruct (lt_ge_cases x 0) as [H|H].
- rewrite 2 sqrt_neg; trivial. reflexivity.
- now rewrite <- Hx.
- apply sqrt_unique. rewrite Hx in *. now apply sqrt_spec.
+ - rewrite 2 sqrt_neg; trivial. + reflexivity.
+ + now rewrite <- Hx.
+ - apply sqrt_unique. rewrite Hx in *. now apply sqrt_spec.
Qed.
(** An alternate specification *)
@@ -101,11 +101,11 @@ Proof.
destruct (sqrt_spec _ Ha) as (LE,LT).
destruct (le_exists_sub _ _ LE) as (r & Hr & Hr').
exists r.
- split. now rewrite add_comm.
- split. trivial.
- apply (add_le_mono_r _ _ (√a)²).
- rewrite <- Hr, add_comm.
- generalize LT. nzsimpl'. now rewrite lt_succ_r, add_assoc.
+ split. - now rewrite add_comm.
+ - split. + trivial.
+ + apply (add_le_mono_r _ _ (√a)²).
+ rewrite <- Hr, add_comm.
+ generalize LT. nzsimpl'. now rewrite lt_succ_r, add_assoc.
Qed.
Lemma sqrt_unique' : forall a b c, 0<=c<=2*b ->
@@ -115,10 +115,10 @@ Proof.
apply sqrt_unique.
rewrite EQ.
split.
- rewrite <- add_0_r at 1. now apply add_le_mono_l.
- nzsimpl. apply lt_succ_r.
- rewrite <- add_assoc. apply add_le_mono_l.
- generalize H; now nzsimpl'.
+ - rewrite <- add_0_r at 1. now apply add_le_mono_l.
+ - nzsimpl. apply lt_succ_r.
+ rewrite <- add_assoc. apply add_le_mono_l.
+ generalize H; now nzsimpl'.
Qed.
(** Sqrt is exact on squares *)
@@ -127,7 +127,7 @@ Lemma sqrt_square : forall a, 0<=a -> √(a²) == a.
Proof.
intros a Ha.
apply sqrt_unique' with 0.
- split. order. apply mul_nonneg_nonneg; order'. now nzsimpl.
+ - split. + order. + apply mul_nonneg_nonneg; order'. - now nzsimpl.
Qed.
(** Sqrt and predecessors of squares *)
@@ -138,14 +138,14 @@ Proof.
apply sqrt_unique.
assert (EQ := lt_succ_pred 0 a Ha).
rewrite EQ. split.
- apply lt_succ_r.
- rewrite (lt_succ_pred 0).
- assert (0 <= P a) by (now rewrite <- lt_succ_r, EQ).
- assert (P a < a) by (now rewrite <- le_succ_l, EQ).
- apply mul_lt_mono_nonneg; trivial.
- now apply mul_pos_pos.
- apply le_succ_l.
- rewrite (lt_succ_pred 0). reflexivity. now apply mul_pos_pos.
+ - apply lt_succ_r.
+ rewrite (lt_succ_pred 0).
+ + assert (0 <= P a) by (now rewrite <- lt_succ_r, EQ).
+ assert (P a < a) by (now rewrite <- le_succ_l, EQ).
+ apply mul_lt_mono_nonneg; trivial.
+ + now apply mul_pos_pos.
+ - apply le_succ_l.
+ rewrite (lt_succ_pred 0). + reflexivity. + now apply mul_pos_pos.
Qed.
(** Sqrt is a monotone function (but not a strict one) *)
@@ -154,13 +154,13 @@ Lemma sqrt_le_mono : forall a b, a <= b -> √a <= √b.
Proof.
intros a b Hab.
destruct (lt_ge_cases a 0) as [Ha|Ha].
- rewrite (sqrt_neg _ Ha). apply sqrt_nonneg.
- assert (Hb : 0 <= b) by order.
- destruct (sqrt_spec a Ha) as (LE,_).
- destruct (sqrt_spec b Hb) as (_,LT).
- apply lt_succ_r.
- apply square_lt_simpl_nonneg; try order.
- now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
+ - rewrite (sqrt_neg _ Ha). apply sqrt_nonneg.
+ - assert (Hb : 0 <= b) by order.
+ destruct (sqrt_spec a Ha) as (LE,_).
+ destruct (sqrt_spec b Hb) as (_,LT).
+ apply lt_succ_r.
+ apply square_lt_simpl_nonneg; try order.
+ now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
Qed.
(** No reverse result for <=, consider for instance √2 <= √1 *)
@@ -169,16 +169,16 @@ Lemma sqrt_lt_cancel : forall a b, √a < √b -> a < b.
Proof.
intros a b H.
destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite (sqrt_neg b Hb) in H; generalize (sqrt_nonneg a); order.
- destruct (lt_ge_cases a 0) as [Ha|Ha]; [order|].
- destruct (sqrt_spec a Ha) as (_,LT).
- destruct (sqrt_spec b Hb) as (LE,_).
- apply le_succ_l in H.
- assert ((S (√a))² <= (√b)²).
- apply mul_le_mono_nonneg; trivial.
- now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
- now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
- order.
+ - rewrite (sqrt_neg b Hb) in H; generalize (sqrt_nonneg a); order.
+ - destruct (lt_ge_cases a 0) as [Ha|Ha]; [order|].
+ destruct (sqrt_spec a Ha) as (_,LT).
+ destruct (sqrt_spec b Hb) as (LE,_).
+ apply le_succ_l in H.
+ assert ((S (√a))² <= (√b)²).
+ + apply mul_le_mono_nonneg; trivial.
+ * now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
+ * now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
+ + order.
Qed.
(** When left side is a square, we have an equivalence for <= *)
@@ -186,11 +186,11 @@ Qed.
Lemma sqrt_le_square : forall a b, 0<=a -> 0<=b -> (b²<=a <-> b <= √a).
Proof.
intros a b Ha Hb. split; intros H.
- rewrite <- (sqrt_square b); trivial.
- now apply sqrt_le_mono.
- destruct (sqrt_spec a Ha) as (LE,LT).
- transitivity (√a)²; trivial.
- now apply mul_le_mono_nonneg.
+ - rewrite <- (sqrt_square b); trivial.
+ now apply sqrt_le_mono.
+ - destruct (sqrt_spec a Ha) as (LE,LT).
+ transitivity (√a)²; trivial.
+ now apply mul_le_mono_nonneg.
Qed.
(** When right side is a square, we have an equivalence for < *)
@@ -198,10 +198,10 @@ Qed.
Lemma sqrt_lt_square : forall a b, 0<=a -> 0<=b -> (a<b² <-> √a < b).
Proof.
intros a b Ha Hb. split; intros H.
- destruct (sqrt_spec a Ha) as (LE,_).
- apply square_lt_simpl_nonneg; try order.
- rewrite <- (sqrt_square b Hb) in H.
- now apply sqrt_lt_cancel.
+ - destruct (sqrt_spec a Ha) as (LE,_).
+ apply square_lt_simpl_nonneg; try order.
+ - rewrite <- (sqrt_square b Hb) in H.
+ now apply sqrt_lt_cancel.
Qed.
(** Sqrt and basic constants *)
@@ -218,14 +218,14 @@ Qed.
Lemma sqrt_2 : √2 == 1.
Proof.
- apply sqrt_unique' with 1. nzsimpl; split; order'. now nzsimpl'.
+ apply sqrt_unique' with 1. - nzsimpl; split; order'. - now nzsimpl'.
Qed.
Lemma sqrt_pos : forall a, 0 < √a <-> 0 < a.
Proof.
- intros a. split; intros Ha. apply sqrt_lt_cancel. now rewrite sqrt_0.
- rewrite <- le_succ_l, <- one_succ, <- sqrt_1. apply sqrt_le_mono.
- now rewrite one_succ, le_succ_l.
+ intros a. split; intros Ha. - apply sqrt_lt_cancel. now rewrite sqrt_0.
+ - rewrite <- le_succ_l, <- one_succ, <- sqrt_1. apply sqrt_le_mono.
+ now rewrite one_succ, le_succ_l.
Qed.
Lemma sqrt_lt_lin : forall a, 1<a -> √a<a.
@@ -239,11 +239,11 @@ Lemma sqrt_le_lin : forall a, 0<=a -> √a<=a.
Proof.
intros a Ha.
destruct (le_gt_cases a 0) as [H|H].
- setoid_replace a with 0 by order. now rewrite sqrt_0.
- destruct (le_gt_cases a 1) as [H'|H'].
- rewrite <- le_succ_l, <- one_succ in H.
- setoid_replace a with 1 by order. now rewrite sqrt_1.
- now apply lt_le_incl, sqrt_lt_lin.
+ - setoid_replace a with 0 by order. now rewrite sqrt_0.
+ - destruct (le_gt_cases a 1) as [H'|H'].
+ + rewrite <- le_succ_l, <- one_succ in H.
+ setoid_replace a with 1 by order. now rewrite sqrt_1.
+ + now apply lt_le_incl, sqrt_lt_lin.
Qed.
(** Sqrt and multiplication. *)
@@ -255,28 +255,28 @@ Lemma sqrt_mul_below : forall a b, √a * √b <= √(a*b).
Proof.
intros a b.
destruct (lt_ge_cases a 0) as [Ha|Ha].
- rewrite (sqrt_neg a Ha). nzsimpl. apply sqrt_nonneg.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite (sqrt_neg b Hb). nzsimpl. apply sqrt_nonneg.
- assert (Ha':=sqrt_nonneg a).
- assert (Hb':=sqrt_nonneg b).
- apply sqrt_le_square; try now apply mul_nonneg_nonneg.
- rewrite mul_shuffle1.
- apply mul_le_mono_nonneg; try now apply mul_nonneg_nonneg.
- now apply sqrt_spec.
- now apply sqrt_spec.
+ - rewrite (sqrt_neg a Ha). nzsimpl. apply sqrt_nonneg.
+ - destruct (lt_ge_cases b 0) as [Hb|Hb].
+ + rewrite (sqrt_neg b Hb). nzsimpl. apply sqrt_nonneg.
+ + assert (Ha':=sqrt_nonneg a).
+ assert (Hb':=sqrt_nonneg b).
+ apply sqrt_le_square; try now apply mul_nonneg_nonneg.
+ rewrite mul_shuffle1.
+ apply mul_le_mono_nonneg; try now apply mul_nonneg_nonneg.
+ * now apply sqrt_spec.
+ * now apply sqrt_spec.
Qed.
Lemma sqrt_mul_above : forall a b, 0<=a -> 0<=b -> √(a*b) < S (√a) * S (√b).
Proof.
intros a b Ha Hb.
apply sqrt_lt_square.
- now apply mul_nonneg_nonneg.
- apply mul_nonneg_nonneg.
- now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
- now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
- rewrite mul_shuffle1.
- apply mul_lt_mono_nonneg; trivial; now apply sqrt_spec.
+ - now apply mul_nonneg_nonneg.
+ - apply mul_nonneg_nonneg.
+ + now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
+ + now apply lt_le_incl, lt_succ_r, sqrt_nonneg.
+ - rewrite mul_shuffle1.
+ apply mul_lt_mono_nonneg; trivial; now apply sqrt_spec.
Qed.
(** And we can't find better approximations in general.
@@ -296,73 +296,73 @@ Proof.
intros a Ha.
apply lt_succ_r.
apply sqrt_lt_square.
- now apply le_le_succ_r.
- apply le_le_succ_r, le_le_succ_r, sqrt_nonneg.
- rewrite <- (add_1_l (S (√a))).
- apply lt_le_trans with (1²+(S (√a))²).
- rewrite mul_1_l, add_1_l, <- succ_lt_mono.
- now apply sqrt_spec.
- apply add_square_le. order'. apply le_le_succ_r, sqrt_nonneg.
+ - now apply le_le_succ_r.
+ - apply le_le_succ_r, le_le_succ_r, sqrt_nonneg.
+ - rewrite <- (add_1_l (S (√a))).
+ apply lt_le_trans with (1²+(S (√a))²).
+ + rewrite mul_1_l, add_1_l, <- succ_lt_mono.
+ now apply sqrt_spec.
+ + apply add_square_le. * order'. * apply le_le_succ_r, sqrt_nonneg.
Qed.
Lemma sqrt_succ_or : forall a, 0<=a -> √(S a) == S (√a) \/ √(S a) == √a.
Proof.
intros a Ha.
destruct (le_gt_cases (√(S a)) (√a)) as [H|H].
- right. generalize (sqrt_le_mono _ _ (le_succ_diag_r a)); order.
- left. apply le_succ_l in H. generalize (sqrt_succ_le a Ha); order.
+ - right. generalize (sqrt_le_mono _ _ (le_succ_diag_r a)); order.
+ - left. apply le_succ_l in H. generalize (sqrt_succ_le a Ha); order.
Qed.
Lemma sqrt_eq_succ_iff_square : forall a, 0<=a ->
(√(S a) == S (√a) <-> exists b, 0<b /\ S a == b²).
Proof.
intros a Ha. split.
- intros EQ. exists (S (√a)).
- split. apply lt_succ_r, sqrt_nonneg.
- generalize (proj2 (sqrt_spec a Ha)). rewrite <- le_succ_l.
- assert (Ha' : 0 <= S a) by now apply le_le_succ_r.
- generalize (proj1 (sqrt_spec (S a) Ha')). rewrite EQ; order.
- intros (b & Hb & H).
- rewrite H. rewrite sqrt_square; try order.
- symmetry.
- rewrite <- (lt_succ_pred 0 b Hb). f_equiv.
- rewrite <- (lt_succ_pred 0 b²) in H. apply succ_inj in H.
- now rewrite H, sqrt_pred_square.
- now apply mul_pos_pos.
+ - intros EQ. exists (S (√a)).
+ split. + apply lt_succ_r, sqrt_nonneg.
+ + generalize (proj2 (sqrt_spec a Ha)). rewrite <- le_succ_l.
+ assert (Ha' : 0 <= S a) by now apply le_le_succ_r.
+ generalize (proj1 (sqrt_spec (S a) Ha')). rewrite EQ; order.
+ - intros (b & Hb & H).
+ rewrite H. rewrite sqrt_square; try order.
+ symmetry.
+ rewrite <- (lt_succ_pred 0 b Hb). f_equiv.
+ rewrite <- (lt_succ_pred 0 b²) in H. + apply succ_inj in H.
+ now rewrite H, sqrt_pred_square.
+ + now apply mul_pos_pos.
Qed.
(** Sqrt and addition *)
Lemma sqrt_add_le : forall a b, √(a+b) <= √a + √b.
Proof.
- assert (AUX : forall a b, a<0 -> √(a+b) <= √a + √b).
- intros a b Ha. rewrite (sqrt_neg a Ha). nzsimpl.
- apply sqrt_le_mono.
- rewrite <- (add_0_l b) at 2.
- apply add_le_mono_r; order.
- intros a b.
- destruct (lt_ge_cases a 0) as [Ha|Ha]. now apply AUX.
- destruct (lt_ge_cases b 0) as [Hb|Hb].
- rewrite (add_comm a), (add_comm (√a)); now apply AUX.
- assert (Ha':=sqrt_nonneg a).
- assert (Hb':=sqrt_nonneg b).
- rewrite <- lt_succ_r.
- apply sqrt_lt_square.
- now apply add_nonneg_nonneg.
- now apply lt_le_incl, lt_succ_r, add_nonneg_nonneg.
- destruct (sqrt_spec a Ha) as (_,LTa).
- destruct (sqrt_spec b Hb) as (_,LTb).
- revert LTa LTb. nzsimpl. rewrite 3 lt_succ_r.
- intros LTa LTb.
- assert (H:=add_le_mono _ _ _ _ LTa LTb).
- etransitivity; [eexact H|]. clear LTa LTb H.
- rewrite <- (add_assoc _ (√a) (√a)).
- rewrite <- (add_assoc _ (√b) (√b)).
- rewrite add_shuffle1.
- rewrite <- (add_assoc _ (√a + √b)).
- rewrite (add_shuffle1 (√a) (√b)).
- apply add_le_mono_r.
- now apply add_square_le.
+ assert (AUX : forall a b, a<0 -> √(a+b) <= √a + √b).
+ - intros a b Ha. rewrite (sqrt_neg a Ha). nzsimpl.
+ apply sqrt_le_mono.
+ rewrite <- (add_0_l b) at 2.
+ apply add_le_mono_r; order.
+ - intros a b.
+ destruct (lt_ge_cases a 0) as [Ha|Ha]. + now apply AUX.
+ + destruct (lt_ge_cases b 0) as [Hb|Hb].
+ * rewrite (add_comm a), (add_comm (√a)); now apply AUX.
+ * assert (Ha':=sqrt_nonneg a).
+ assert (Hb':=sqrt_nonneg b).
+ rewrite <- lt_succ_r.
+ apply sqrt_lt_square.
+ -- now apply add_nonneg_nonneg.
+ -- now apply lt_le_incl, lt_succ_r, add_nonneg_nonneg.
+ -- destruct (sqrt_spec a Ha) as (_,LTa).
+ destruct (sqrt_spec b Hb) as (_,LTb).
+ revert LTa LTb. nzsimpl. rewrite 3 lt_succ_r.
+ intros LTa LTb.
+ assert (H:=add_le_mono _ _ _ _ LTa LTb).
+ etransitivity; [eexact H|]. clear LTa LTb H.
+ rewrite <- (add_assoc _ (√a) (√a)).
+ rewrite <- (add_assoc _ (√b) (√b)).
+ rewrite add_shuffle1.
+ rewrite <- (add_assoc _ (√a + √b)).
+ rewrite (add_shuffle1 (√a) (√b)).
+ apply add_le_mono_r.
+ now apply add_square_le.
Qed.
(** convexity inequality for sqrt: sqrt of middle is above middle
@@ -374,12 +374,12 @@ Proof.
assert (Ha':=sqrt_nonneg a).
assert (Hb':=sqrt_nonneg b).
apply sqrt_le_square.
- apply mul_nonneg_nonneg. order'. now apply add_nonneg_nonneg.
- now apply add_nonneg_nonneg.
- transitivity (2*((√a)² + (√b)²)).
- now apply square_add_le.
- apply mul_le_mono_nonneg_l. order'.
- apply add_le_mono; now apply sqrt_spec.
+ - apply mul_nonneg_nonneg. + order'. + now apply add_nonneg_nonneg.
+ - now apply add_nonneg_nonneg.
+ - transitivity (2*((√a)² + (√b)²)).
+ + now apply square_add_le.
+ + apply mul_le_mono_nonneg_l. * order'.
+ * apply add_le_mono; now apply sqrt_spec.
Qed.
End NZSqrtProp.
@@ -430,8 +430,8 @@ Qed.
Lemma sqrt_up_nonneg : forall a, 0<=√°a.
Proof.
intros. destruct (le_gt_cases a 0) as [Ha|Ha].
- now rewrite sqrt_up_eqn0.
- rewrite sqrt_up_eqn; trivial. apply le_le_succ_r, sqrt_nonneg.
+ - now rewrite sqrt_up_eqn0.
+ - rewrite sqrt_up_eqn; trivial. apply le_le_succ_r, sqrt_nonneg.
Qed.
(** [sqrt_up] is a morphism *)
@@ -439,8 +439,8 @@ Qed.
Instance sqrt_up_wd : Proper (eq==>eq) sqrt_up.
Proof.
assert (Proper (eq==>eq==>Logic.eq) compare).
- intros x x' Hx y y' Hy. do 2 case compare_spec; trivial; order.
- intros x x' Hx; unfold sqrt_up; rewrite Hx; case compare; now rewrite ?Hx.
+ - intros x x' Hx y y' Hy. do 2 case compare_spec; trivial; order.
+ - intros x x' Hx; unfold sqrt_up; rewrite Hx; case compare; now rewrite ?Hx.
Qed.
(** The spec of [sqrt_up] indeed determines it *)
@@ -463,9 +463,9 @@ Lemma sqrt_up_square : forall a, 0<=a -> √°(a²) == a.
Proof.
intros a Ha.
le_elim Ha.
- rewrite sqrt_up_eqn by (now apply mul_pos_pos).
- rewrite sqrt_pred_square; trivial. apply (lt_succ_pred 0); trivial.
- rewrite sqrt_up_eqn0; trivial. rewrite <- Ha. now nzsimpl.
+ - rewrite sqrt_up_eqn by (now apply mul_pos_pos).
+ rewrite sqrt_pred_square; trivial. apply (lt_succ_pred 0); trivial.
+ - rewrite sqrt_up_eqn0; trivial. rewrite <- Ha. now nzsimpl.
Qed.
(** [sqrt_up] and successors of squares *)
@@ -500,10 +500,10 @@ Qed.
Lemma le_sqrt_sqrt_up : forall a, √a <= √°a.
Proof.
intros a. unfold sqrt_up. case compare_spec; intros H.
- rewrite <- H, sqrt_0. order.
- rewrite <- (lt_succ_pred 0 a H) at 1. apply sqrt_succ_le.
- apply lt_succ_r. now rewrite (lt_succ_pred 0 a H).
- now rewrite sqrt_neg.
+ - rewrite <- H, sqrt_0. order.
+ - rewrite <- (lt_succ_pred 0 a H) at 1. apply sqrt_succ_le.
+ apply lt_succ_r. now rewrite (lt_succ_pred 0 a H).
+ - now rewrite sqrt_neg.
Qed.
Lemma le_sqrt_up_succ_sqrt : forall a, √°a <= S (√a).
@@ -517,21 +517,21 @@ Qed.
Lemma sqrt_sqrt_up_spec : forall a, 0<=a -> (√a)² <= a <= (√°a)².
Proof.
intros a H. split.
- now apply sqrt_spec.
- le_elim H.
- now apply sqrt_up_spec.
- now rewrite <-H, sqrt_up_0, mul_0_l.
+ - now apply sqrt_spec.
+ - le_elim H.
+ + now apply sqrt_up_spec.
+ + now rewrite <-H, sqrt_up_0, mul_0_l.
Qed.
Lemma sqrt_sqrt_up_exact :
forall a, 0<=a -> (√a == √°a <-> exists b, 0<=b /\ a == b²).
Proof.
intros a Ha.
- split. intros. exists √a.
- split. apply sqrt_nonneg.
- generalize (sqrt_sqrt_up_spec a Ha). rewrite <-H. destruct 1; order.
- intros (b & Hb & Hb'). rewrite Hb'.
- now rewrite sqrt_square, sqrt_up_square.
+ split. - intros. exists √a.
+ split. + apply sqrt_nonneg.
+ + generalize (sqrt_sqrt_up_spec a Ha). rewrite <-H. destruct 1; order.
+ - intros (b & Hb & Hb'). rewrite Hb'.
+ now rewrite sqrt_square, sqrt_up_square.
Qed.
(** [sqrt_up] is a monotone function (but not a strict one) *)
@@ -540,9 +540,9 @@ Lemma sqrt_up_le_mono : forall a b, a <= b -> √°a <= √°b.
Proof.
intros a b H.
destruct (le_gt_cases a 0) as [Ha|Ha].
- rewrite (sqrt_up_eqn0 _ Ha). apply sqrt_up_nonneg.
- rewrite 2 sqrt_up_eqn by order. rewrite <- succ_le_mono.
- apply sqrt_le_mono, succ_le_mono. rewrite 2 (lt_succ_pred 0); order.
+ - rewrite (sqrt_up_eqn0 _ Ha). apply sqrt_up_nonneg.
+ - rewrite 2 sqrt_up_eqn by order. rewrite <- succ_le_mono.
+ apply sqrt_le_mono, succ_le_mono. rewrite 2 (lt_succ_pred 0); order.
Qed.
(** No reverse result for <=, consider for instance √°3 <= √°2 *)
@@ -551,10 +551,10 @@ Lemma sqrt_up_lt_cancel : forall a b, √°a < √°b -> a < b.
Proof.
intros a b H.
destruct (le_gt_cases b 0) as [Hb|Hb].
- rewrite (sqrt_up_eqn0 _ Hb) in H; generalize (sqrt_up_nonneg a); order.
- destruct (le_gt_cases a 0) as [Ha|Ha]; [order|].
- rewrite <- (lt_succ_pred 0 a Ha), <- (lt_succ_pred 0 b Hb), <- succ_lt_mono.
- apply sqrt_lt_cancel, succ_lt_mono. now rewrite <- 2 sqrt_up_eqn.
+ - rewrite (sqrt_up_eqn0 _ Hb) in H; generalize (sqrt_up_nonneg a); order.
+ - destruct (le_gt_cases a 0) as [Ha|Ha]; [order|].
+ rewrite <- (lt_succ_pred 0 a Ha), <- (lt_succ_pred 0 b Hb), <- succ_lt_mono.
+ apply sqrt_lt_cancel, succ_lt_mono. now rewrite <- 2 sqrt_up_eqn.
Qed.
(** When left side is a square, we have an equivalence for < *)
@@ -562,10 +562,10 @@ Qed.
Lemma sqrt_up_lt_square : forall a b, 0<=a -> 0<=b -> (b² < a <-> b < √°a).
Proof.
intros a b Ha Hb. split; intros H.
- destruct (sqrt_up_spec a) as (LE,LT).
- apply le_lt_trans with b²; trivial using square_nonneg.
- apply square_lt_simpl_nonneg; try order. apply sqrt_up_nonneg.
- apply sqrt_up_lt_cancel. now rewrite sqrt_up_square.
+ - destruct (sqrt_up_spec a) as (LE,LT).
+ + apply le_lt_trans with b²; trivial using square_nonneg.
+ + apply square_lt_simpl_nonneg; try order. apply sqrt_up_nonneg.
+ - apply sqrt_up_lt_cancel. now rewrite sqrt_up_square.
Qed.
(** When right side is a square, we have an equivalence for <= *)
@@ -573,17 +573,17 @@ Qed.
Lemma sqrt_up_le_square : forall a b, 0<=a -> 0<=b -> (a <= b² <-> √°a <= b).
Proof.
intros a b Ha Hb. split; intros H.
- rewrite <- (sqrt_up_square b Hb).
- now apply sqrt_up_le_mono.
- apply square_le_mono_nonneg in H; [|now apply sqrt_up_nonneg].
- transitivity (√°a)²; trivial. now apply sqrt_sqrt_up_spec.
+ - rewrite <- (sqrt_up_square b Hb).
+ now apply sqrt_up_le_mono.
+ - apply square_le_mono_nonneg in H; [|now apply sqrt_up_nonneg].
+ transitivity (√°a)²; trivial. now apply sqrt_sqrt_up_spec.
Qed.
Lemma sqrt_up_pos : forall a, 0 < √°a <-> 0 < a.
Proof.
- intros a. split; intros Ha. apply sqrt_up_lt_cancel. now rewrite sqrt_up_0.
- rewrite <- le_succ_l, <- one_succ, <- sqrt_up_1. apply sqrt_up_le_mono.
- now rewrite one_succ, le_succ_l.
+ intros a. split; intros Ha. - apply sqrt_up_lt_cancel. now rewrite sqrt_up_0.
+ - rewrite <- le_succ_l, <- one_succ, <- sqrt_up_1. apply sqrt_up_le_mono.
+ now rewrite one_succ, le_succ_l.
Qed.
Lemma sqrt_up_lt_lin : forall a, 2<a -> √°a < a.
@@ -599,11 +599,11 @@ Lemma sqrt_up_le_lin : forall a, 0<=a -> √°a<=a.
Proof.
intros a Ha.
le_elim Ha.
- rewrite sqrt_up_eqn; trivial. apply le_succ_l.
- apply le_lt_trans with (P a). apply sqrt_le_lin.
- now rewrite <- lt_succ_r, (lt_succ_pred 0).
- rewrite <- (lt_succ_pred 0 a) at 2; trivial. apply lt_succ_diag_r.
- now rewrite <- Ha, sqrt_up_0.
+ - rewrite sqrt_up_eqn; trivial. apply le_succ_l.
+ apply le_lt_trans with (P a). + apply sqrt_le_lin.
+ now rewrite <- lt_succ_r, (lt_succ_pred 0).
+ + rewrite <- (lt_succ_pred 0 a) at 2; trivial. apply lt_succ_diag_r.
+ - now rewrite <- Ha, sqrt_up_0.
Qed.
(** [sqrt_up] and multiplication. *)
@@ -615,23 +615,23 @@ Lemma sqrt_up_mul_above : forall a b, 0<=a -> 0<=b -> √°(a*b) <= √°a * √
Proof.
intros a b Ha Hb.
apply sqrt_up_le_square.
- now apply mul_nonneg_nonneg.
- apply mul_nonneg_nonneg; apply sqrt_up_nonneg.
- rewrite mul_shuffle1.
- apply mul_le_mono_nonneg; trivial; now apply sqrt_sqrt_up_spec.
+ - now apply mul_nonneg_nonneg.
+ - apply mul_nonneg_nonneg; apply sqrt_up_nonneg.
+ - rewrite mul_shuffle1.
+ apply mul_le_mono_nonneg; trivial; now apply sqrt_sqrt_up_spec.
Qed.
Lemma sqrt_up_mul_below : forall a b, 0<a -> 0<b -> (P √°a)*(P √°b) < √°(a*b).
Proof.
intros a b Ha Hb.
apply sqrt_up_lt_square.
- apply mul_nonneg_nonneg; order.
- apply mul_nonneg_nonneg; apply lt_succ_r.
- rewrite (lt_succ_pred 0); now rewrite sqrt_up_pos.
- rewrite (lt_succ_pred 0); now rewrite sqrt_up_pos.
- rewrite mul_shuffle1.
- apply mul_lt_mono_nonneg; trivial using square_nonneg;
- now apply sqrt_up_spec.
+ - apply mul_nonneg_nonneg; order.
+ - apply mul_nonneg_nonneg; apply lt_succ_r.
+ + rewrite (lt_succ_pred 0); now rewrite sqrt_up_pos.
+ + rewrite (lt_succ_pred 0); now rewrite sqrt_up_pos.
+ - rewrite mul_shuffle1.
+ apply mul_lt_mono_nonneg; trivial using square_nonneg;
+ now apply sqrt_up_spec.
Qed.
(** And we can't find better approximations in general.
@@ -650,37 +650,37 @@ Lemma sqrt_up_succ_le : forall a, 0<=a -> √°(S a) <= S (√°a).
Proof.
intros a Ha.
apply sqrt_up_le_square.
- now apply le_le_succ_r.
- apply le_le_succ_r, sqrt_up_nonneg.
- rewrite <- (add_1_l (√°a)).
- apply le_trans with (1²+(√°a)²).
- rewrite mul_1_l, add_1_l, <- succ_le_mono.
- now apply sqrt_sqrt_up_spec.
- apply add_square_le. order'. apply sqrt_up_nonneg.
+ - now apply le_le_succ_r.
+ - apply le_le_succ_r, sqrt_up_nonneg.
+ - rewrite <- (add_1_l (√°a)).
+ apply le_trans with (1²+(√°a)²).
+ + rewrite mul_1_l, add_1_l, <- succ_le_mono.
+ now apply sqrt_sqrt_up_spec.
+ + apply add_square_le. * order'. * apply sqrt_up_nonneg.
Qed.
Lemma sqrt_up_succ_or : forall a, 0<=a -> √°(S a) == S (√°a) \/ √°(S a) == √°a.
Proof.
intros a Ha.
destruct (le_gt_cases (√°(S a)) (√°a)) as [H|H].
- right. generalize (sqrt_up_le_mono _ _ (le_succ_diag_r a)); order.
- left. apply le_succ_l in H. generalize (sqrt_up_succ_le a Ha); order.
+ - right. generalize (sqrt_up_le_mono _ _ (le_succ_diag_r a)); order.
+ - left. apply le_succ_l in H. generalize (sqrt_up_succ_le a Ha); order.
Qed.
Lemma sqrt_up_eq_succ_iff_square : forall a, 0<=a ->
(√°(S a) == S (√°a) <-> exists b, 0<=b /\ a == b²).
Proof.
intros a Ha. split.
- intros EQ.
- le_elim Ha.
- exists (√°a). split. apply sqrt_up_nonneg.
- generalize (proj2 (sqrt_up_spec a Ha)).
- assert (Ha' : 0 < S a) by (apply lt_succ_r; order').
- generalize (proj1 (sqrt_up_spec (S a) Ha')).
- rewrite EQ, pred_succ, lt_succ_r. order.
- exists 0. nzsimpl. now split.
- intros (b & Hb & H).
- now rewrite H, sqrt_up_succ_square, sqrt_up_square.
+ - intros EQ.
+ le_elim Ha.
+ + exists (√°a). split. * apply sqrt_up_nonneg.
+ * generalize (proj2 (sqrt_up_spec a Ha)).
+ assert (Ha' : 0 < S a) by (apply lt_succ_r; order').
+ generalize (proj1 (sqrt_up_spec (S a) Ha')).
+ rewrite EQ, pred_succ, lt_succ_r. order.
+ + exists 0. nzsimpl. now split.
+ - intros (b & Hb & H).
+ now rewrite H, sqrt_up_succ_square, sqrt_up_square.
Qed.
(** [sqrt_up] and addition *)
@@ -688,21 +688,21 @@ Qed.
Lemma sqrt_up_add_le : forall a b, √°(a+b) <= √°a + √°b.
Proof.
assert (AUX : forall a b, a<=0 -> √°(a+b) <= √°a + √°b).
- intros a b Ha. rewrite (sqrt_up_eqn0 a Ha). nzsimpl.
- apply sqrt_up_le_mono.
- rewrite <- (add_0_l b) at 2.
- apply add_le_mono_r; order.
- intros a b.
- destruct (le_gt_cases a 0) as [Ha|Ha]. now apply AUX.
- destruct (le_gt_cases b 0) as [Hb|Hb].
- rewrite (add_comm a), (add_comm (√°a)); now apply AUX.
- rewrite 2 sqrt_up_eqn; trivial.
- nzsimpl. rewrite <- succ_le_mono.
- transitivity (√(P a) + √b).
- rewrite <- (lt_succ_pred 0 a Ha) at 1. nzsimpl. apply sqrt_add_le.
- apply add_le_mono_l.
- apply le_sqrt_sqrt_up.
- now apply add_pos_pos.
+ - intros a b Ha. rewrite (sqrt_up_eqn0 a Ha). nzsimpl.
+ apply sqrt_up_le_mono.
+ rewrite <- (add_0_l b) at 2.
+ apply add_le_mono_r; order.
+ - intros a b.
+ destruct (le_gt_cases a 0) as [Ha|Ha]. + now apply AUX.
+ + destruct (le_gt_cases b 0) as [Hb|Hb].
+ * rewrite (add_comm a), (add_comm (√°a)); now apply AUX.
+ * rewrite 2 sqrt_up_eqn; trivial.
+ -- nzsimpl. rewrite <- succ_le_mono.
+ transitivity (√(P a) + √b).
+ ++ rewrite <- (lt_succ_pred 0 a Ha) at 1. nzsimpl. apply sqrt_add_le.
+ ++ apply add_le_mono_l.
+ apply le_sqrt_sqrt_up.
+ -- now apply add_pos_pos.
Qed.
(** Convexity-like inequality for [sqrt_up]: [sqrt_up] of middle is above middle
@@ -712,25 +712,24 @@ Qed.
Lemma add_sqrt_up_le : forall a b, 0<=a -> 0<=b -> √°a + √°b <= S √°(2*(a+b)).
Proof.
intros a b Ha Hb.
- le_elim Ha.
- le_elim Hb.
- rewrite 3 sqrt_up_eqn; trivial.
- nzsimpl. rewrite <- 2 succ_le_mono.
- etransitivity; [eapply add_sqrt_le|].
- apply lt_succ_r. now rewrite (lt_succ_pred 0 a Ha).
- apply lt_succ_r. now rewrite (lt_succ_pred 0 b Hb).
- apply sqrt_le_mono.
- apply lt_succ_r. rewrite (lt_succ_pred 0).
- apply mul_lt_mono_pos_l. order'.
- apply add_lt_mono.
- apply le_succ_l. now rewrite (lt_succ_pred 0).
- apply le_succ_l. now rewrite (lt_succ_pred 0).
- apply mul_pos_pos. order'. now apply add_pos_pos.
- apply mul_pos_pos. order'. now apply add_pos_pos.
- rewrite <- Hb, sqrt_up_0. nzsimpl. apply le_le_succ_r, sqrt_up_le_mono.
- rewrite <- (mul_1_l a) at 1. apply mul_le_mono_nonneg_r; order'.
- rewrite <- Ha, sqrt_up_0. nzsimpl. apply le_le_succ_r, sqrt_up_le_mono.
- rewrite <- (mul_1_l b) at 1. apply mul_le_mono_nonneg_r; order'.
+ le_elim Ha;[le_elim Hb|].
+ - rewrite 3 sqrt_up_eqn; trivial.
+ + nzsimpl. rewrite <- 2 succ_le_mono.
+ etransitivity; [eapply add_sqrt_le|].
+ * apply lt_succ_r. now rewrite (lt_succ_pred 0 a Ha).
+ * apply lt_succ_r. now rewrite (lt_succ_pred 0 b Hb).
+ * apply sqrt_le_mono.
+ apply lt_succ_r. rewrite (lt_succ_pred 0).
+ -- apply mul_lt_mono_pos_l. ++ order'.
+ ++ apply add_lt_mono.
+ ** apply le_succ_l. now rewrite (lt_succ_pred 0).
+ ** apply le_succ_l. now rewrite (lt_succ_pred 0).
+ -- apply mul_pos_pos. ++ order'. ++ now apply add_pos_pos.
+ + apply mul_pos_pos. * order'. * now apply add_pos_pos.
+ - rewrite <- Hb, sqrt_up_0. nzsimpl. apply le_le_succ_r, sqrt_up_le_mono.
+ rewrite <- (mul_1_l a) at 1. apply mul_le_mono_nonneg_r; order'.
+ - rewrite <- Ha, sqrt_up_0. nzsimpl. apply le_le_succ_r, sqrt_up_le_mono.
+ rewrite <- (mul_1_l b) at 1. apply mul_le_mono_nonneg_r; order'.
Qed.
End NZSqrtUpProp.
diff --git a/theories/Program/Subset.v b/theories/Program/Subset.v
index 1c89b6c3b1..ae366204ac 100644
--- a/theories/Program/Subset.v
+++ b/theories/Program/Subset.v
@@ -73,10 +73,10 @@ Proof.
simpl.
split ; intros ; subst.
- inversion H.
- reflexivity.
+ - inversion H.
+ reflexivity.
- pi.
+ - pi.
Qed.
(* Somewhat trivial definition, but not unfolded automatically hence we can match on [match_eq ?A ?B ?x ?f]
diff --git a/theories/Program/Wf.v b/theories/Program/Wf.v
index f9d23e3cf6..092c1d6f48 100644
--- a/theories/Program/Wf.v
+++ b/theories/Program/Wf.v
@@ -97,15 +97,15 @@ Section Measure_well_founded.
Proof with auto.
unfold well_founded.
cut (forall (a: M) (a0: T), m a0 = a -> Acc MR a0).
- intros.
+ + intros.
apply (H (m a))...
- apply (@well_founded_ind M R wf (fun mm => forall a, m a = mm -> Acc MR a)).
- intros.
- apply Acc_intro.
- intros.
- unfold MR in H1.
- rewrite H0 in H1.
- apply (H (m y))...
+ + apply (@well_founded_ind M R wf (fun mm => forall a, m a = mm -> Acc MR a)).
+ intros.
+ apply Acc_intro.
+ intros.
+ unfold MR in H1.
+ rewrite H0 in H1.
+ apply (H (m y))...
Defined.
End Measure_well_founded.
@@ -245,8 +245,8 @@ Module WfExtensionality.
intros ; apply Fix_eq ; auto.
intros.
assert(f = g).
- extensionality y ; apply H.
- rewrite H0 ; auto.
+ - extensionality y ; apply H.
+ - rewrite H0 ; auto.
Qed.
(** Tactic to unfold once a definition based on [Fix_sub]. *)
diff --git a/theories/Relations/Operators_Properties.v b/theories/Relations/Operators_Properties.v
index e82a673445..0a60d96afc 100644
--- a/theories/Relations/Operators_Properties.v
+++ b/theories/Relations/Operators_Properties.v
@@ -45,9 +45,8 @@ Section Properties.
Lemma clos_rt_is_preorder : preorder R*.
Proof.
apply Build_preorder.
- exact (rt_refl A R).
-
- exact (rt_trans A R).
+ - exact (rt_refl A R).
+ - exact (rt_trans A R).
Qed.
(** Idempotency of the reflexive-transitive closure operator *)
@@ -82,8 +81,8 @@ Section Properties.
inclusion (clos_refl R) (clos_refl_trans R).
Proof.
induction 1 as [? ?| ].
- constructor; auto.
- constructor 2.
+ - constructor; auto.
+ - constructor 2.
Qed.
Lemma clos_rt_t : forall x y z,
@@ -100,9 +99,9 @@ Section Properties.
Lemma clos_rst_is_equiv : equivalence A (clos_refl_sym_trans R).
Proof.
apply Build_equivalence.
- exact (rst_refl A R).
- exact (rst_trans A R).
- exact (rst_sym A R).
+ - exact (rst_refl A R).
+ - exact (rst_trans A R).
+ - exact (rst_sym A R).
Qed.
(** Idempotency of the reflexive-symmetric-transitive closure operator *)
@@ -130,18 +129,18 @@ Section Properties.
Lemma clos_t1n_trans : forall x y, clos_trans_1n R x y -> clos_trans R x y.
Proof.
induction 1.
- left; assumption.
- right with y; auto.
- left; auto.
+ - left; assumption.
+ - right with y; auto.
+ left; auto.
Qed.
Lemma clos_trans_t1n : forall x y, clos_trans R x y -> clos_trans_1n R x y.
Proof.
induction 1.
- left; assumption.
- generalize IHclos_trans2; clear IHclos_trans2; induction IHclos_trans1.
- right with y; auto.
- right with y; auto.
+ - left; assumption.
+ - generalize IHclos_trans2; clear IHclos_trans2; induction IHclos_trans1.
+ + right with y; auto.
+ + right with y; auto.
eapply IHIHclos_trans1; auto.
apply clos_t1n_trans; auto.
Qed.
@@ -150,8 +149,8 @@ Section Properties.
clos_trans R x y <-> clos_trans_1n R x y.
Proof.
split.
- apply clos_trans_t1n.
- apply clos_t1n_trans.
+ - apply clos_trans_t1n.
+ - apply clos_t1n_trans.
Qed.
(** Direct transitive closure vs right-step extension *)
@@ -159,29 +158,29 @@ Section Properties.
Lemma clos_tn1_trans : forall x y, clos_trans_n1 R x y -> clos_trans R x y.
Proof.
induction 1.
- left; assumption.
- right with y; auto.
- left; assumption.
+ - left; assumption.
+ - right with y; auto.
+ left; assumption.
Qed.
Lemma clos_trans_tn1 : forall x y, clos_trans R x y -> clos_trans_n1 R x y.
Proof.
induction 1.
- left; assumption.
- elim IHclos_trans2.
- intro y0; right with y.
- auto.
- auto.
- intros.
- right with y0; auto.
+ - left; assumption.
+ - elim IHclos_trans2.
+ + intro y0; right with y.
+ * auto.
+ * auto.
+ + intros.
+ right with y0; auto.
Qed.
Lemma clos_trans_tn1_iff : forall x y,
clos_trans R x y <-> clos_trans_n1 R x y.
Proof.
split.
- apply clos_trans_tn1.
- apply clos_tn1_trans.
+ - apply clos_trans_tn1.
+ - apply clos_tn1_trans.
Qed.
(** Direct reflexive-transitive closure is equivalent to
@@ -203,31 +202,31 @@ Section Properties.
clos_refl_trans_1n R x y -> clos_refl_trans R x y.
Proof.
induction 1.
- constructor 2.
- constructor 3 with y; auto.
- constructor 1; auto.
+ - constructor 2.
+ - constructor 3 with y; auto.
+ constructor 1; auto.
Qed.
Lemma clos_rt_rt1n : forall x y,
clos_refl_trans R x y -> clos_refl_trans_1n R x y.
Proof.
induction 1.
- apply clos_rt1n_step; assumption.
- left.
- generalize IHclos_refl_trans2; clear IHclos_refl_trans2;
- induction IHclos_refl_trans1; auto.
+ - apply clos_rt1n_step; assumption.
+ - left.
+ - generalize IHclos_refl_trans2; clear IHclos_refl_trans2;
+ induction IHclos_refl_trans1; auto.
- right with y; auto.
- eapply IHIHclos_refl_trans1; auto.
- apply clos_rt1n_rt; auto.
+ right with y; auto.
+ eapply IHIHclos_refl_trans1; auto.
+ apply clos_rt1n_rt; auto.
Qed.
Lemma clos_rt_rt1n_iff : forall x y,
clos_refl_trans R x y <-> clos_refl_trans_1n R x y.
Proof.
split.
- apply clos_rt_rt1n.
- apply clos_rt1n_rt.
+ - apply clos_rt_rt1n.
+ - apply clos_rt1n_rt.
Qed.
(** Direct reflexive-transitive closure is equivalent to
@@ -237,28 +236,28 @@ Section Properties.
clos_refl_trans_n1 R x y -> clos_refl_trans R x y.
Proof.
induction 1.
- constructor 2.
- constructor 3 with y; auto.
- constructor 1; assumption.
+ - constructor 2.
+ - constructor 3 with y; auto.
+ constructor 1; assumption.
Qed.
Lemma clos_rt_rtn1 : forall x y,
clos_refl_trans R x y -> clos_refl_trans_n1 R x y.
Proof.
induction 1.
- apply clos_rtn1_step; auto.
- left.
- elim IHclos_refl_trans2; auto.
- intros.
- right with y0; auto.
+ - apply clos_rtn1_step; auto.
+ - left.
+ - elim IHclos_refl_trans2; auto.
+ intros.
+ right with y0; auto.
Qed.
Lemma clos_rt_rtn1_iff : forall x y,
clos_refl_trans R x y <-> clos_refl_trans_n1 R x y.
Proof.
split.
- apply clos_rt_rtn1.
- apply clos_rtn1_rt.
+ - apply clos_rt_rtn1.
+ - apply clos_rtn1_rt.
Qed.
(** Induction on the left transitive step *)
@@ -271,14 +270,14 @@ Section Properties.
intros.
revert H H0.
induction H1; intros; auto with sets.
- apply H1 with x; auto with sets.
+ - apply H1 with x; auto with sets.
- apply IHclos_refl_trans2.
- apply IHclos_refl_trans1; auto with sets.
+ - apply IHclos_refl_trans2.
+ + apply IHclos_refl_trans1; auto with sets.
- intros.
- apply H0 with y0; auto with sets.
- apply rt_trans with y; auto with sets.
+ + intros.
+ apply H0 with y0; auto with sets.
+ apply rt_trans with y; auto with sets.
Qed.
(** Induction on the right transitive step *)
@@ -311,45 +310,45 @@ Section Properties.
clos_refl_sym_trans_1n R x y -> clos_refl_sym_trans R x y.
Proof.
induction 1.
- constructor 2.
- constructor 4 with y; auto.
- case H;[constructor 1|constructor 3; constructor 1]; auto.
+ - constructor 2.
+ - constructor 4 with y; auto.
+ case H;[constructor 1|constructor 3; constructor 1]; auto.
Qed.
Lemma clos_rst1n_trans : forall x y z, clos_refl_sym_trans_1n R x y ->
clos_refl_sym_trans_1n R y z -> clos_refl_sym_trans_1n R x z.
induction 1.
- auto.
- intros; right with y; eauto.
+ - auto.
+ - intros; right with y; eauto.
Qed.
Lemma clos_rst1n_sym : forall x y, clos_refl_sym_trans_1n R x y ->
clos_refl_sym_trans_1n R y x.
Proof.
intros x y H; elim H.
- constructor 1.
- intros x0 y0 z D H0 H1; apply clos_rst1n_trans with y0; auto.
- right with x0.
- tauto.
- left.
+ - constructor 1.
+ - intros x0 y0 z D H0 H1; apply clos_rst1n_trans with y0; auto.
+ right with x0.
+ + tauto.
+ + left.
Qed.
Lemma clos_rst_rst1n : forall x y,
clos_refl_sym_trans R x y -> clos_refl_sym_trans_1n R x y.
induction 1.
- constructor 2 with y; auto.
- constructor 1.
- constructor 1.
- apply clos_rst1n_sym; auto.
- eapply clos_rst1n_trans; eauto.
+ - constructor 2 with y; auto.
+ constructor 1.
+ - constructor 1.
+ - apply clos_rst1n_sym; auto.
+ - eapply clos_rst1n_trans; eauto.
Qed.
Lemma clos_rst_rst1n_iff : forall x y,
clos_refl_sym_trans R x y <-> clos_refl_sym_trans_1n R x y.
Proof.
split.
- apply clos_rst_rst1n.
- apply clos_rst1n_rst.
+ - apply clos_rst_rst1n.
+ - apply clos_rst1n_rst.
Qed.
(** Direct reflexive-symmetric-transitive closure is equivalent to
@@ -359,9 +358,9 @@ Section Properties.
clos_refl_sym_trans_n1 R x y -> clos_refl_sym_trans R x y.
Proof.
induction 1.
- constructor 2.
- constructor 4 with y; auto.
- case H;[constructor 1|constructor 3; constructor 1]; auto.
+ - constructor 2.
+ - constructor 4 with y; auto.
+ case H;[constructor 1|constructor 3; constructor 1]; auto.
Qed.
Lemma clos_rstn1_trans : forall x y z, clos_refl_sym_trans_n1 R x y ->
@@ -369,39 +368,39 @@ Section Properties.
Proof.
intros x y z H1 H2.
induction H2.
- auto.
- intros.
- right with y0; eauto.
+ - auto.
+ - intros.
+ right with y0; eauto.
Qed.
Lemma clos_rstn1_sym : forall x y, clos_refl_sym_trans_n1 R x y ->
clos_refl_sym_trans_n1 R y x.
Proof.
intros x y H; elim H.
- constructor 1.
- intros y0 z D H0 H1. apply clos_rstn1_trans with y0; auto.
- right with z.
- tauto.
- left.
+ - constructor 1.
+ - intros y0 z D H0 H1. apply clos_rstn1_trans with y0; auto.
+ right with z.
+ + tauto.
+ + left.
Qed.
Lemma clos_rst_rstn1 : forall x y,
clos_refl_sym_trans R x y -> clos_refl_sym_trans_n1 R x y.
Proof.
induction 1.
- constructor 2 with x; auto.
- constructor 1.
- constructor 1.
- apply clos_rstn1_sym; auto.
- eapply clos_rstn1_trans; eauto.
+ - constructor 2 with x; auto.
+ constructor 1.
+ - constructor 1.
+ - apply clos_rstn1_sym; auto.
+ - eapply clos_rstn1_trans; eauto.
Qed.
Lemma clos_rst_rstn1_iff : forall x y,
clos_refl_sym_trans R x y <-> clos_refl_sym_trans_n1 R x y.
Proof.
split.
- apply clos_rst_rstn1.
- apply clos_rstn1_rst.
+ - apply clos_rst_rstn1.
+ - apply clos_rstn1_rst.
Qed.
End Equivalences.
diff --git a/theories/Sets/Constructive_sets.v b/theories/Sets/Constructive_sets.v
index f2475af124..862c3238e7 100644
--- a/theories/Sets/Constructive_sets.v
+++ b/theories/Sets/Constructive_sets.v
@@ -103,8 +103,8 @@ Section Ensembles_facts.
forall (A:Ensemble U) (x y:U), In U (Add U A x) y -> In U A y \/ x = y.
Proof.
intros A x y H'; induction H'.
- left; assumption.
- right; apply Singleton_inv; assumption.
+ - left; assumption.
+ - right; apply Singleton_inv; assumption.
Qed.
Lemma Intersection_inv :
diff --git a/theories/Sets/Partial_Order.v b/theories/Sets/Partial_Order.v
index 5b51c7b953..811e42f091 100644
--- a/theories/Sets/Partial_Order.v
+++ b/theories/Sets/Partial_Order.v
@@ -71,11 +71,11 @@ Section Partial_order_facts.
elim D; simpl.
intros C R H' H'0; elim H'0.
intros H'1 H'2 H'3 x y z H'4 H'5; split.
- apply H'2 with (y := y); tauto.
- red; intro H'6.
- elim H'4; intros H'7 H'8; apply H'8; clear H'4.
- apply H'3; auto.
- rewrite H'6; tauto.
+ - apply H'2 with (y := y); tauto.
+ - red; intro H'6.
+ elim H'4; intros H'7 H'8; apply H'8; clear H'4.
+ apply H'3; auto.
+ rewrite H'6; tauto.
Qed.
Lemma Strict_Rel_Transitive_with_Rel_left :
@@ -87,11 +87,11 @@ Section Partial_order_facts.
elim D; simpl.
intros C R H' H'0; elim H'0.
intros H'1 H'2 H'3 x y z H'4 H'5; split.
- apply H'2 with (y := y); tauto.
- red; intro H'6.
- elim H'5; intros H'7 H'8; apply H'8; clear H'5.
- apply H'3; auto.
- rewrite <- H'6; auto.
+ - apply H'2 with (y := y); tauto.
+ - red; intro H'6.
+ elim H'5; intros H'7 H'8; apply H'8; clear H'5.
+ apply H'3; auto.
+ rewrite <- H'6; auto.
Qed.
Lemma Strict_Rel_Transitive : Transitive U (Strict_Rel_of U D).
diff --git a/theories/Sets/Permut.v b/theories/Sets/Permut.v
index 86a500dfdd..5cd9f52c6b 100644
--- a/theories/Sets/Permut.v
+++ b/theories/Sets/Permut.v
@@ -33,8 +33,8 @@ Section Axiomatisation.
forall x y z t:U, cong x y -> cong z t -> cong (op x z) (op y t).
Proof.
intros; apply cong_trans with (op y z).
- apply cong_left; trivial.
- apply cong_right; trivial.
+ - apply cong_left; trivial.
+ - apply cong_right; trivial.
Qed.
Lemma comm_right : forall x y z:U, cong (op x (op y z)) (op x (op z y)).
@@ -51,27 +51,27 @@ Section Axiomatisation.
Proof.
intros.
apply cong_trans with (op x (op y z)).
- apply op_ass.
- apply cong_trans with (op x (op z y)).
- apply cong_right; apply op_comm.
- apply cong_sym; apply op_ass.
+ - apply op_ass.
+ - apply cong_trans with (op x (op z y)).
+ + apply cong_right; apply op_comm.
+ + apply cong_sym; apply op_ass.
Qed.
Lemma perm_left : forall x y z:U, cong (op x (op y z)) (op y (op x z)).
Proof.
intros.
apply cong_trans with (op (op x y) z).
- apply cong_sym; apply op_ass.
- apply cong_trans with (op (op y x) z).
- apply cong_left; apply op_comm.
- apply op_ass.
+ - apply cong_sym; apply op_ass.
+ - apply cong_trans with (op (op y x) z).
+ + apply cong_left; apply op_comm.
+ + apply op_ass.
Qed.
Lemma op_rotate : forall x y z t:U, cong (op x (op y z)) (op z (op x y)).
Proof.
intros; apply cong_trans with (op (op x y) z).
- apply cong_sym; apply op_ass.
- apply op_comm.
+ - apply cong_sym; apply op_ass.
+ - apply op_comm.
Qed.
(** Needed for treesort ... *)
@@ -80,10 +80,10 @@ Section Axiomatisation.
Proof.
intros.
apply cong_trans with (op x (op (op y t) z)).
- apply cong_right; apply perm_right.
- apply cong_trans with (op (op x (op y t)) z).
- apply cong_sym; apply op_ass.
- apply cong_left; apply perm_left.
+ - apply cong_right; apply perm_right.
+ - apply cong_trans with (op (op x (op y t)) z).
+ + apply cong_sym; apply op_ass.
+ + apply cong_left; apply perm_left.
Qed.
End Axiomatisation.
diff --git a/theories/Sets/Powerset.v b/theories/Sets/Powerset.v
index 50a7e401f8..5b352f05fa 100644
--- a/theories/Sets/Powerset.v
+++ b/theories/Sets/Powerset.v
@@ -154,9 +154,9 @@ Theorem Union_is_Lub :
Lub (Ensemble U) (Power_set_PO A) (Couple (Ensemble U) a b) (Union U a b).
intros A a b H' H'0.
apply Lub_definition; simpl.
-apply Upper_Bound_definition; simpl; auto with sets.
-intros y H'1; elim H'1; auto with sets.
-intros y H'1; elim H'1; simpl; auto with sets.
+- apply Upper_Bound_definition; simpl; auto with sets.
+ intros y H'1; elim H'1; auto with sets.
+- intros y H'1; elim H'1; simpl; auto with sets.
Qed.
Theorem Intersection_is_Glb :
@@ -167,12 +167,12 @@ Theorem Intersection_is_Glb :
(Intersection U a b).
intros A a b H' H'0.
apply Glb_definition; simpl.
-apply Lower_Bound_definition; simpl; auto with sets.
-apply Definition_of_Power_set.
-generalize Inclusion_is_transitive; intro IT; red in IT; apply IT with a;
- auto with sets.
-intros y H'1; elim H'1; auto with sets.
-intros y H'1; elim H'1; simpl; auto with sets.
+- apply Lower_Bound_definition; simpl; auto with sets.
+ + apply Definition_of_Power_set.
+ generalize Inclusion_is_transitive; intro IT; red in IT; apply IT with a;
+ auto with sets.
+ + intros y H'1; elim H'1; auto with sets.
+- intros y H'1; elim H'1; simpl; auto with sets.
Qed.
End The_power_set_partial_order.
diff --git a/theories/Sets/Powerset_facts.v b/theories/Sets/Powerset_facts.v
index 81b475ac6e..784f2ce0ff 100644
--- a/theories/Sets/Powerset_facts.v
+++ b/theories/Sets/Powerset_facts.v
@@ -84,8 +84,8 @@ Section Sets_as_an_algebra.
forall x y:U, Union U (Singleton U x) (Singleton U y) = Couple U x y.
Proof.
intros x y; apply Extensionality_Ensembles; split; red.
- intros x0 H'; elim H'; (intros x1 H'0; elim H'0; auto with sets).
- intros x0 H'; elim H'; auto with sets.
+ - intros x0 H'; elim H'; (intros x1 H'0; elim H'0; auto with sets).
+ - intros x0 H'; elim H'; auto with sets.
Qed.
Theorem Triple_as_union :
@@ -94,10 +94,10 @@ Section Sets_as_an_algebra.
Triple U x y z.
Proof.
intros x y z; apply Extensionality_Ensembles; split; red.
- intros x0 H'; elim H'.
- intros x1 H'0; elim H'0; (intros x2 H'1; elim H'1; auto with sets).
- intros x1 H'0; elim H'0; auto with sets.
- intros x0 H'; elim H'; auto with sets.
+ - intros x0 H'; elim H'.
+ + intros x1 H'0; elim H'0; (intros x2 H'1; elim H'1; auto with sets).
+ + intros x1 H'0; elim H'0; auto with sets.
+ - intros x0 H'; elim H'; auto with sets.
Qed.
Theorem Triple_as_Couple : forall x y:U, Couple U x y = Triple U x x y.
@@ -132,10 +132,10 @@ Section Sets_as_an_algebra.
intros A B C.
apply Extensionality_Ensembles.
split; red; intros x H'.
- elim H'.
- intros x0 H'0 H'1; generalize H'0.
- elim H'1; auto with sets.
- elim H'; intros x0 H'0; elim H'0; auto with sets.
+ - elim H'.
+ intros x0 H'0 H'1; generalize H'0.
+ elim H'1; auto with sets.
+ - elim H'; intros x0 H'0; elim H'0; auto with sets.
Qed.
Lemma Distributivity_l
@@ -157,13 +157,13 @@ Section Sets_as_an_algebra.
intros A B C.
apply Extensionality_Ensembles.
split; red; intros x H'.
- elim H'; auto with sets.
- intros x0 H'0; elim H'0; auto with sets.
- elim H'.
- intros x0 H'0; elim H'0; auto with sets.
- intros x1 H'1 H'2; try exact H'2.
- generalize H'1.
- elim H'2; auto with sets.
+ - elim H'; auto with sets.
+ intros x0 H'0; elim H'0; auto with sets.
+ - elim H'.
+ intros x0 H'0; elim H'0; auto with sets.
+ intros x1 H'1 H'2; try exact H'2.
+ generalize H'1.
+ elim H'2; auto with sets.
Qed.
Theorem Union_add :
@@ -188,11 +188,11 @@ Section Sets_as_an_algebra.
intros X x H'; unfold Subtract.
apply Extensionality_Ensembles.
split; red; auto with sets.
- intros x0 H'0; elim H'0; auto with sets.
- intros x0 H'0; apply Setminus_intro; auto with sets.
- red; intro H'1; elim H'1.
- lapply (Singleton_inv U x x0); auto with sets.
- intro H'4; apply H'; rewrite H'4; auto with sets.
+ - intros x0 H'0; elim H'0; auto with sets.
+ - intros x0 H'0; apply Setminus_intro; auto with sets.
+ red; intro H'1; elim H'1.
+ lapply (Singleton_inv U x x0); auto with sets.
+ intro H'4; apply H'; rewrite H'4; auto with sets.
Qed.
Lemma singlx : forall x y:U, In U (Add U (Empty_set U) x) y -> x = y.
@@ -320,7 +320,9 @@ Section Sets_as_an_algebra.
Setminus A s1 (Union A s2 s3) = Setminus A (Setminus A s1 s2) s3.
Proof.
intros. apply Extensionality_Ensembles. split.
- * intros x H. inversion H. constructor. intuition. contradict H1. intuition.
+ * intros x H. inversion H. constructor.
+ -- intuition.
+ -- contradict H1. intuition.
* intros x H. inversion H. inversion H0. constructor; intuition. inversion H4; intuition.
Qed.
diff --git a/theories/Sets/Relations_1_facts.v b/theories/Sets/Relations_1_facts.v
index d275487e15..17bdefcdbf 100644
--- a/theories/Sets/Relations_1_facts.v
+++ b/theories/Sets/Relations_1_facts.v
@@ -45,12 +45,12 @@ Theorem Equiv_from_preorder :
Proof.
intros U R H'; elim H'; intros H'0 H'1.
apply Definition_of_equivalence.
-red in H'0; auto 10 with sets.
-2: red; intros x y h; elim h; intros H'3 H'4; auto 10 with sets.
-red in H'1; red; auto 10 with sets.
-intros x y z h; elim h; intros H'3 H'4; clear h.
-intro h; elim h; intros H'5 H'6; clear h.
-split; apply H'1 with y; auto 10 with sets.
+- red in H'0; auto 10 with sets.
+- red in H'1; red; auto 10 with sets.
+ intros x y z h; elim h; intros H'3 H'4; clear h.
+ intro h; elim h; intros H'5 H'6; clear h.
+ split; apply H'1 with y; auto 10 with sets.
+- red; intros x y h; elim h; intros H'3 H'4; auto 10 with sets.
Qed.
Hint Resolve Equiv_from_preorder : core.
diff --git a/theories/Sets/Relations_2_facts.v b/theories/Sets/Relations_2_facts.v
index 36da368447..48d0ea55c9 100644
--- a/theories/Sets/Relations_2_facts.v
+++ b/theories/Sets/Relations_2_facts.v
@@ -53,8 +53,8 @@ Theorem Rstar_contains_Rplus :
Proof.
intros U R; red.
intros x y H'; elim H'.
-generalize Rstar_contains_R; intro T; red in T; auto with sets.
-intros x0 y0 z H'0 H'1 H'2; apply Rstar_n with y0; auto with sets.
+- generalize Rstar_contains_R; intro T; red in T; auto with sets.
+- intros x0 y0 z H'0 H'1 H'2; apply Rstar_n with y0; auto with sets.
Qed.
Theorem Rstar_transitive :
@@ -79,9 +79,9 @@ Proof.
generalize Rstar_contains_R; intro T; red in T.
intros U R; unfold same_relation, contains.
split; intros x y H'; elim H'; auto with sets.
-generalize Rstar_transitive; intro T1; red in T1.
-intros x0 y0 z H'0 H'1 H'2 H'3; apply T1 with y0; auto with sets.
-intros x0 y0 z H'0 H'1 H'2; apply Rstar1_n with y0; auto with sets.
+- generalize Rstar_transitive; intro T1; red in T1.
+ intros x0 y0 z H'0 H'1 H'2 H'3; apply T1 with y0; auto with sets.
+- intros x0 y0 z H'0 H'1 H'2; apply Rstar1_n with y0; auto with sets.
Qed.
Theorem Rsym_imp_Rstarsym :
@@ -121,12 +121,12 @@ Proof.
generalize Rstar_contains_Rplus; intro T; red in T.
generalize Rstar_transitive; intro T1; red in T1.
intros U R x y z H'; elim H'.
-intros x0 H'0; elim H'0.
-intros x1 y0 H'1; exists y0; auto with sets.
-intros x1 y0 z0 H'1 H'2 H'3; exists y0; auto with sets.
-intros x0 y0 z0 H'0 H'1 H'2 H'3; exists y0.
-split; [ try assumption | idtac ].
-apply T1 with z0; auto with sets.
+- intros x0 H'0; elim H'0.
+ + intros x1 y0 H'1; exists y0; auto with sets.
+ + intros x1 y0 z0 H'1 H'2 H'3; exists y0; auto with sets.
+- intros x0 y0 z0 H'0 H'1 H'2 H'3; exists y0.
+ split; [ try assumption | idtac ].
+ apply T1 with z0; auto with sets.
Qed.
Theorem Lemma1 :
@@ -137,17 +137,17 @@ Theorem Lemma1 :
forall a:U, R x a -> exists z : _, Rstar U R a z /\ R b z.
Proof.
intros U R H' x b H'0; elim H'0.
-intros x0 a H'1; exists a; auto with sets.
-intros x0 y z H'1 H'2 H'3 a H'4.
-red in H'.
-specialize H' with (x := x0) (a := a) (b := y); lapply H';
- [ intro H'8; lapply H'8;
- [ intro H'9; try exact H'9; clear H'8 H' | clear H'8 H' ]
- | clear H' ]; auto with sets.
-elim H'9.
-intros t H'5; elim H'5; intros H'6 H'7; try exact H'6; clear H'5.
-elim (H'3 t); auto with sets.
-intros z1 H'5; elim H'5; intros H'8 H'10; try exact H'8; clear H'5.
-exists z1; split; [ idtac | assumption ].
-apply Rstar_n with t; auto with sets.
+- intros x0 a H'1; exists a; auto with sets.
+- intros x0 y z H'1 H'2 H'3 a H'4.
+ red in H'.
+ specialize H' with (x := x0) (a := a) (b := y); lapply H';
+ [ intro H'8; lapply H'8;
+ [ intro H'9; try exact H'9; clear H'8 H' | clear H'8 H' ]
+ | clear H' ]; auto with sets.
+ elim H'9.
+ intros t H'5; elim H'5; intros H'6 H'7; try exact H'6; clear H'5.
+ elim (H'3 t); auto with sets.
+ intros z1 H'5; elim H'5; intros H'8 H'10; try exact H'8; clear H'5.
+ exists z1; split; [ idtac | assumption ].
+ apply Rstar_n with t; auto with sets.
Qed.
diff --git a/theories/Sets/Relations_3_facts.v b/theories/Sets/Relations_3_facts.v
index 18ea019526..a4806ea0a6 100644
--- a/theories/Sets/Relations_3_facts.v
+++ b/theories/Sets/Relations_3_facts.v
@@ -57,21 +57,21 @@ intro x; red; intros a b H'0.
unfold coherent at 1.
generalize b; clear b.
elim H'0; clear H'0.
-intros x0 b H'1; exists b; auto with sets.
-intros x0 y z H'1 H'2 H'3 b H'4.
-generalize (Lemma1 U R); intro h; lapply h;
- [ intro H'0; generalize (H'0 x0 b); intro h0; lapply h0;
- [ intro H'5; generalize (H'5 y); intro h1; lapply h1;
- [ intro h2; elim h2; intros z0 h3; elim h3; intros H'6 H'7;
+- intros x0 b H'1; exists b; auto with sets.
+- intros x0 y z H'1 H'2 H'3 b H'4.
+ generalize (Lemma1 U R); intro h; lapply h;
+ [ intro H'0; generalize (H'0 x0 b); intro h0; lapply h0;
+ [ intro H'5; generalize (H'5 y); intro h1; lapply h1;
+ [ intro h2; elim h2; intros z0 h3; elim h3; intros H'6 H'7;
clear h h0 h1 h2 h3
- | clear h h0 h1 ]
- | clear h h0 ]
- | clear h ]; auto with sets.
-generalize (H'3 z0); intro h; lapply h;
- [ intro h0; elim h0; intros z1 h1; elim h1; intros H'8 H'9; clear h h0 h1
- | clear h ]; auto with sets.
-exists z1; split; auto with sets.
-apply Rstar_n with z0; auto with sets.
+ | clear h h0 h1 ]
+ | clear h h0 ]
+ | clear h ]; auto with sets.
+ generalize (H'3 z0); intro h; lapply h;
+ [ intro h0; elim h0; intros z1 h1; elim h1; intros H'8 H'9; clear h h0 h1
+ | clear h ]; auto with sets.
+ exists z1; split; auto with sets.
+ apply Rstar_n with z0; auto with sets.
Qed.
Theorem Strong_confluence_direct :
@@ -82,31 +82,31 @@ intro x; red; intros a b H'0.
unfold coherent at 1.
generalize b; clear b.
elim H'0; clear H'0.
-intros x0 b H'1; exists b; auto with sets.
-intros x0 y z H'1 H'2 H'3 b H'4.
-cut (ex (fun t:U => Rstar U R y t /\ R b t)).
-intro h; elim h; intros t h0; elim h0; intros H'0 H'5; clear h h0.
-generalize (H'3 t); intro h; lapply h;
- [ intro h0; elim h0; intros z0 h1; elim h1; intros H'6 H'7; clear h h0 h1
- | clear h ]; auto with sets.
-exists z0; split; [ assumption | idtac ].
-apply Rstar_n with t; auto with sets.
-generalize H'1; generalize y; clear H'1.
-elim H'4.
-intros x1 y0 H'0; exists y0; auto with sets.
-intros x1 y0 z0 H'0 H'1 H'5 y1 H'6.
-red in H'.
-generalize (H' x1 y0 y1); intro h; lapply h;
- [ intro H'7; lapply H'7;
- [ intro h0; elim h0; intros z1 h1; elim h1; intros H'8 H'9;
- clear h H'7 h0 h1
- | clear h ]
- | clear h ]; auto with sets.
-generalize (H'5 z1); intro h; lapply h;
- [ intro h0; elim h0; intros t h1; elim h1; intros H'7 H'10; clear h h0 h1
- | clear h ]; auto with sets.
-exists t; split; auto with sets.
-apply Rstar_n with z1; auto with sets.
+- intros x0 b H'1; exists b; auto with sets.
+- intros x0 y z H'1 H'2 H'3 b H'4.
+ cut (ex (fun t:U => Rstar U R y t /\ R b t)).
+ + intro h; elim h; intros t h0; elim h0; intros H'0 H'5; clear h h0.
+ generalize (H'3 t); intro h; lapply h;
+ [ intro h0; elim h0; intros z0 h1; elim h1; intros H'6 H'7; clear h h0 h1
+ | clear h ]; auto with sets.
+ exists z0; split; [ assumption | idtac ].
+ apply Rstar_n with t; auto with sets.
+ + generalize H'1; generalize y; clear H'1.
+ elim H'4.
+ * intros x1 y0 H'0; exists y0; auto with sets.
+ * intros x1 y0 z0 H'0 H'1 H'5 y1 H'6.
+ red in H'.
+ generalize (H' x1 y0 y1); intro h; lapply h;
+ [ intro H'7; lapply H'7;
+ [ intro h0; elim h0; intros z1 h1; elim h1; intros H'8 H'9;
+ clear h H'7 h0 h1
+ | clear h ]
+ | clear h ]; auto with sets.
+ generalize (H'5 z1); intro h; lapply h;
+ [ intro h0; elim h0; intros t h1; elim h1; intros H'7 H'10; clear h h0 h1
+ | clear h ]; auto with sets.
+ exists t; split; auto with sets.
+ apply Rstar_n with z1; auto with sets.
Qed.
Theorem Noetherian_contains_Noetherian :
@@ -131,41 +131,41 @@ generalize (Rstar_cases U R x0 y); intro h; lapply h;
| intro h1; elim h1; intros u h2; elim h2; intros H'5 H'6;
clear h h0 h1 h2 ]
| clear h ]; auto with sets.
-elim h1; auto with sets.
-generalize (Rstar_cases U R x0 z); intro h; lapply h;
- [ intro h0; elim h0;
- [ clear h h0; intro h1
- | intro h1; elim h1; intros v h2; elim h2; intros H'7 H'8;
- clear h h0 h1 h2 ]
- | clear h ]; auto with sets.
-elim h1; generalize coherent_symmetric; intro t; red in t; auto with sets.
-unfold Locally_confluent, locally_confluent, coherent in H'0.
-generalize (H'0 x0 u v); intro h; lapply h;
- [ intro H'9; lapply H'9;
- [ intro h0; elim h0; intros t h1; elim h1; intros H'10 H'11;
- clear h H'9 h0 h1
- | clear h ]
- | clear h ]; auto with sets.
-clear H'0.
-unfold coherent at 1 in H'2.
-generalize (H'2 u); intro h; lapply h;
- [ intro H'0; generalize (H'0 y t); intro h0; lapply h0;
- [ intro H'9; lapply H'9;
- [ intro h1; elim h1; intros y1 h2; elim h2; intros H'12 H'13;
- clear h h0 H'9 h1 h2
- | clear h h0 ]
- | clear h h0 ]
- | clear h ]; auto with sets.
-generalize Rstar_transitive; intro T; red in T.
-generalize (H'2 v); intro h; lapply h;
- [ intro H'9; generalize (H'9 y1 z); intro h0; lapply h0;
- [ intro H'14; lapply H'14;
- [ intro h1; elim h1; intros z1 h2; elim h2; intros H'15 H'16;
- clear h h0 H'14 h1 h2
- | clear h h0 ]
- | clear h h0 ]
- | clear h ]; auto with sets.
-red; (exists z1; split); auto with sets.
-apply T with y1; auto with sets.
-apply T with t; auto with sets.
+- elim h1; auto with sets.
+- generalize (Rstar_cases U R x0 z); intro h; lapply h;
+ [ intro h0; elim h0;
+ [ clear h h0; intro h1
+ | intro h1; elim h1; intros v h2; elim h2; intros H'7 H'8;
+ clear h h0 h1 h2 ]
+ | clear h ]; auto with sets.
+ + elim h1; generalize coherent_symmetric; intro t; red in t; auto with sets.
+ + unfold Locally_confluent, locally_confluent, coherent in H'0.
+ generalize (H'0 x0 u v); intro h; lapply h;
+ [ intro H'9; lapply H'9;
+ [ intro h0; elim h0; intros t h1; elim h1; intros H'10 H'11;
+ clear h H'9 h0 h1
+ | clear h ]
+ | clear h ]; auto with sets.
+ clear H'0.
+ unfold coherent at 1 in H'2.
+ generalize (H'2 u); intro h; lapply h;
+ [ intro H'0; generalize (H'0 y t); intro h0; lapply h0;
+ [ intro H'9; lapply H'9;
+ [ intro h1; elim h1; intros y1 h2; elim h2; intros H'12 H'13;
+ clear h h0 H'9 h1 h2
+ | clear h h0 ]
+ | clear h h0 ]
+ | clear h ]; auto with sets.
+ generalize Rstar_transitive; intro T; red in T.
+ generalize (H'2 v); intro h; lapply h;
+ [ intro H'9; generalize (H'9 y1 z); intro h0; lapply h0;
+ [ intro H'14; lapply H'14;
+ [ intro h1; elim h1; intros z1 h2; elim h2; intros H'15 H'16;
+ clear h h0 H'14 h1 h2
+ | clear h h0 ]
+ | clear h h0 ]
+ | clear h ]; auto with sets.
+ * red; (exists z1; split); auto with sets.
+ apply T with y1; auto with sets.
+ * apply T with t; auto with sets.
Qed.
diff --git a/theories/Sets/Uniset.v b/theories/Sets/Uniset.v
index 0ff304ed6b..edfffe6ce9 100644
--- a/theories/Sets/Uniset.v
+++ b/theories/Sets/Uniset.v
@@ -174,8 +174,8 @@ Lemma uniset_twist2 :
seq (union x (union (union y z) t)) (union (union y (union x z)) t).
Proof.
intros; apply seq_trans with (union (union x (union y z)) t).
-apply seq_sym; apply union_ass.
-apply seq_left; apply union_perm_left.
+- apply seq_sym; apply union_ass.
+- apply seq_left; apply union_perm_left.
Qed.
(** specific for treesort *)
@@ -186,8 +186,8 @@ Lemma treesort_twist1 :
seq (union x (union u t)) (union (union y (union x t)) z).
Proof.
intros; apply seq_trans with (union x (union (union y z) t)).
-apply seq_right; apply seq_left; trivial.
-apply uniset_twist1.
+- apply seq_right; apply seq_left; trivial.
+- apply uniset_twist1.
Qed.
Lemma treesort_twist2 :
@@ -196,8 +196,8 @@ Lemma treesort_twist2 :
seq (union x (union u t)) (union (union y (union x z)) t).
Proof.
intros; apply seq_trans with (union x (union (union y z) t)).
-apply seq_right; apply seq_left; trivial.
-apply uniset_twist2.
+- apply seq_right; apply seq_left; trivial.
+- apply uniset_twist2.
Qed.
diff --git a/theories/Structures/Equalities.v b/theories/Structures/Equalities.v
index 4143dba547..346c300ee5 100644
--- a/theories/Structures/Equalities.v
+++ b/theories/Structures/Equalities.v
@@ -158,8 +158,10 @@ Module HasEqDec2Bool (E:Eq)(F:HasEqDec E) <: HasEqBool E.
Lemma eqb_eq : forall x y, eqb x y = true <-> E.eq x y.
Proof.
intros x y. unfold eqb. destruct F.eq_dec as [EQ|NEQ].
- auto with *.
- split. discriminate. intro EQ; elim NEQ; auto.
+ - auto with *.
+ - split.
+ + discriminate.
+ + intro EQ; elim NEQ; auto.
Qed.
End HasEqDec2Bool.
@@ -168,8 +170,8 @@ Module HasEqBool2Dec (E:Eq)(F:HasEqBool E) <: HasEqDec E.
Proof.
intros x y. assert (H:=F.eqb_eq x y).
destruct (F.eqb x y); [left|right].
- apply -> H; auto.
- intro EQ. apply H in EQ. discriminate.
+ - apply -> H; auto.
+ - intro EQ. apply H in EQ. discriminate.
Defined.
End HasEqBool2Dec.
diff --git a/theories/Structures/GenericMinMax.v b/theories/Structures/GenericMinMax.v
index 4d04667c01..c314f3f982 100644
--- a/theories/Structures/GenericMinMax.v
+++ b/theories/Structures/GenericMinMax.v
@@ -47,8 +47,8 @@ Module GenericMinMax (Import O:OrderedTypeFull') <: HasMinMax O.
intros H H'.
apply (StrictOrder_Irreflexive x).
rewrite le_lteq in *; destruct H as [H|H].
- transitivity y; auto.
- rewrite H in H'; auto.
+ - transitivity y; auto.
+ - rewrite H in H'; auto.
Qed.
Lemma max_l x y : y<=x -> max x y == x.
@@ -142,8 +142,8 @@ Proof.
intros Eqf Lef x y.
destruct (max_spec x y) as [(H,E)|(H,E)]; rewrite E;
destruct (max_spec (f x) (f y)) as [(H',E')|(H',E')]; auto.
- assert (f x <= f y) by (apply Lef; order). order.
- assert (f y <= f x) by (apply Lef; order). order.
+ - assert (f x <= f y) by (apply Lef; order). order.
+ - assert (f y <= f x) by (apply Lef; order). order.
Qed.
(** *** Semi-lattice algebraic properties of [max] *)
@@ -194,7 +194,11 @@ Proof.
Qed.
Lemma max_le_iff n m p : p <= max n m <-> p <= n \/ p <= m.
-Proof. split. apply max_le. solve_max. Qed.
+Proof.
+ split.
+ - apply max_le.
+ - solve_max.
+Qed.
Lemma max_lt_iff n m p : p < max n m <-> p < n \/ p < m.
Proof.
@@ -282,8 +286,8 @@ Proof.
intros Eqf Lef x y.
destruct (min_spec x y) as [(H,E)|(H,E)]; rewrite E;
destruct (min_spec (f x) (f y)) as [(H',E')|(H',E')]; auto.
- assert (f x <= f y) by (apply Lef; order). order.
- assert (f y <= f x) by (apply Lef; order). order.
+ - assert (f x <= f y) by (apply Lef; order). order.
+ - assert (f y <= f x) by (apply Lef; order). order.
Qed.
Lemma min_id n : min n n == n.
@@ -330,7 +334,11 @@ Proof.
Qed.
Lemma min_le_iff n m p : min n m <= p <-> n <= p \/ m <= p.
-Proof. split. apply min_le. solve_min. Qed.
+Proof.
+ split.
+ - apply min_le.
+ - solve_min.
+Qed.
Lemma min_lt_iff n m p : min n m < p <-> n < p \/ m < p.
Proof.
@@ -377,16 +385,16 @@ Lemma min_max_absorption n m : max n (min n m) == n.
Proof.
intros.
destruct (min_spec n m) as [(C,E)|(C,E)]; rewrite E.
- apply max_l. order.
- destruct (max_spec n m); intuition; order.
+ - apply max_l. order.
+ - destruct (max_spec n m); intuition; order.
Qed.
Lemma max_min_absorption n m : min n (max n m) == n.
Proof.
intros.
destruct (max_spec n m) as [(C,E)|(C,E)]; rewrite E.
- destruct (min_spec n m) as [(C',E')|(C',E')]; auto. order.
- apply min_l; auto. order.
+ - destruct (min_spec n m) as [(C',E')|(C',E')]; auto. order.
+ - apply min_l; auto. order.
Qed.
(** Distributivity *)
@@ -395,16 +403,16 @@ Lemma max_min_distr n m p :
max n (min m p) == min (max n m) (max n p).
Proof.
symmetry. apply min_mono.
- eauto with *.
- repeat red; intros. apply max_le_compat_l; auto.
+ - eauto with *.
+ - repeat red; intros. apply max_le_compat_l; auto.
Qed.
Lemma min_max_distr n m p :
min n (max m p) == max (min n m) (min n p).
Proof.
symmetry. apply max_mono.
- eauto with *.
- repeat red; intros. apply min_le_compat_l; auto.
+ - eauto with *.
+ - repeat red; intros. apply min_le_compat_l; auto.
Qed.
(** Modularity *)
@@ -415,8 +423,8 @@ Proof.
rewrite <- max_min_distr.
destruct (max_spec n p) as [(C,E)|(C,E)]; rewrite E; auto with *.
destruct (min_spec m n) as [(C',E')|(C',E')]; rewrite E'.
- rewrite 2 max_l; try order. rewrite min_le_iff; auto.
- rewrite 2 max_l; try order. rewrite min_le_iff; auto.
+ - rewrite 2 max_l; try order. rewrite min_le_iff; auto.
+ - rewrite 2 max_l; try order. rewrite min_le_iff; auto.
Qed.
Lemma min_max_modular n m p :
@@ -425,8 +433,8 @@ Proof.
intros. rewrite <- min_max_distr.
destruct (min_spec n p) as [(C,E)|(C,E)]; rewrite E; auto with *.
destruct (max_spec m n) as [(C',E')|(C',E')]; rewrite E'.
- rewrite 2 min_l; try order. rewrite max_le_iff; right; order.
- rewrite 2 min_l; try order. rewrite max_le_iff; auto.
+ - rewrite 2 min_l; try order. rewrite max_le_iff; right; order.
+ - rewrite 2 min_l; try order. rewrite max_le_iff; auto.
Qed.
(** Disassociativity *)
@@ -448,8 +456,8 @@ Proof.
intros Eqf Lef x y.
destruct (min_spec x y) as [(H,E)|(H,E)]; rewrite E;
destruct (max_spec (f x) (f y)) as [(H',E')|(H',E')]; auto.
- assert (f y <= f x) by (apply Lef; order). order.
- assert (f x <= f y) by (apply Lef; order). order.
+ - assert (f y <= f x) by (apply Lef; order). order.
+ - assert (f x <= f y) by (apply Lef; order). order.
Qed.
Lemma min_max_antimono f :
@@ -460,8 +468,8 @@ Proof.
intros Eqf Lef x y.
destruct (max_spec x y) as [(H,E)|(H,E)]; rewrite E;
destruct (min_spec (f x) (f y)) as [(H',E')|(H',E')]; auto.
- assert (f y <= f x) by (apply Lef; order). order.
- assert (f x <= f y) by (apply Lef; order). order.
+ - assert (f y <= f x) by (apply Lef; order). order.
+ - assert (f x <= f y) by (apply Lef; order). order.
Qed.
End MinMaxLogicalProperties.
@@ -479,12 +487,12 @@ Lemma max_case_strong n m (P:t -> Type) :
Proof.
intros Compat Hl Hr.
destruct (CompSpec2Type (compare_spec n m)) as [EQ|LT|GT].
-assert (n<=m) by (rewrite le_lteq; auto).
-apply (Compat m), Hr; auto. symmetry; apply max_r; auto.
-assert (n<=m) by (rewrite le_lteq; auto).
-apply (Compat m), Hr; auto. symmetry; apply max_r; auto.
-assert (m<=n) by (rewrite le_lteq; auto).
-apply (Compat n), Hl; auto. symmetry; apply max_l; auto.
+- assert (n<=m) by (rewrite le_lteq; auto).
+ apply (Compat m), Hr; auto. symmetry; apply max_r; auto.
+- assert (n<=m) by (rewrite le_lteq; auto).
+ apply (Compat m), Hr; auto. symmetry; apply max_r; auto.
+- assert (m<=n) by (rewrite le_lteq; auto).
+ apply (Compat n), Hl; auto. symmetry; apply max_l; auto.
Defined.
Lemma max_case n m (P:t -> Type) :
@@ -508,12 +516,12 @@ Lemma min_case_strong n m (P:O.t -> Type) :
Proof.
intros Compat Hl Hr.
destruct (CompSpec2Type (compare_spec n m)) as [EQ|LT|GT].
-assert (n<=m) by (rewrite le_lteq; auto).
-apply (Compat n), Hl; auto. symmetry; apply min_l; auto.
-assert (n<=m) by (rewrite le_lteq; auto).
-apply (Compat n), Hl; auto. symmetry; apply min_l; auto.
-assert (m<=n) by (rewrite le_lteq; auto).
-apply (Compat m), Hr; auto. symmetry; apply min_r; auto.
+- assert (n<=m) by (rewrite le_lteq; auto).
+ apply (Compat n), Hl; auto. symmetry; apply min_l; auto.
+- assert (n<=m) by (rewrite le_lteq; auto).
+ apply (Compat n), Hl; auto. symmetry; apply min_l; auto.
+- assert (m<=n) by (rewrite le_lteq; auto).
+ apply (Compat m), Hr; auto. symmetry; apply min_r; auto.
Defined.
Lemma min_case n m (P:O.t -> Type) :
@@ -624,11 +632,11 @@ Module TOMaxEqDec_to_Compare
Lemma compare_spec : forall x y, CompSpec eq lt x y (compare x y).
Proof.
intros; unfold compare; repeat destruct eq_dec; auto; constructor.
- destruct (lt_total x y); auto.
- absurd (x==y); auto. transitivity (max x y); auto.
- symmetry. apply max_l. rewrite le_lteq; intuition.
- destruct (lt_total y x); auto.
- absurd (max x y == y); auto. apply max_r; rewrite le_lteq; intuition.
+ - destruct (lt_total x y); auto.
+ absurd (x==y); auto. transitivity (max x y); auto.
+ symmetry. apply max_l. rewrite le_lteq; intuition.
+ - destruct (lt_total y x); auto.
+ absurd (max x y == y); auto. apply max_r; rewrite le_lteq; intuition.
Qed.
End TOMaxEqDec_to_Compare.
diff --git a/theories/Structures/Orders.v b/theories/Structures/Orders.v
index 310a22a0a4..7fcf517457 100644
--- a/theories/Structures/Orders.v
+++ b/theories/Structures/Orders.v
@@ -143,8 +143,8 @@ Module Compare2EqBool (Import O:DecStrOrder') <: HasEqBool O.
Proof.
unfold eqb. intros x y.
destruct (compare_spec x y) as [H|H|H]; split; auto; try discriminate.
- intros EQ; rewrite EQ in H; elim (StrictOrder_Irreflexive _ H).
- intros EQ; rewrite EQ in H; elim (StrictOrder_Irreflexive _ H).
+ - intros EQ; rewrite EQ in H; elim (StrictOrder_Irreflexive _ H).
+ - intros EQ; rewrite EQ in H; elim (StrictOrder_Irreflexive _ H).
Qed.
End Compare2EqBool.
@@ -252,9 +252,11 @@ Module OTF_to_TTLB (Import O : OrderedTypeFull') <: TotalTransitiveLeBool.
Proof.
intros. unfold leb. rewrite le_lteq.
destruct (compare_spec x y) as [EQ|LT|GT]; split; auto.
- discriminate.
- intros LE. elim (StrictOrder_Irreflexive x).
- destruct LE as [LT|EQ]. now transitivity y. now rewrite <- EQ in GT.
+ - discriminate.
+ - intros LE. elim (StrictOrder_Irreflexive x).
+ destruct LE as [LT|EQ].
+ + now transitivity y.
+ + now rewrite <- EQ in GT.
Qed.
Lemma leb_total : forall x y, leb x y \/ leb y x.
@@ -267,10 +269,10 @@ Module OTF_to_TTLB (Import O : OrderedTypeFull') <: TotalTransitiveLeBool.
Proof.
intros x y z. rewrite !leb_le, !le_lteq.
intros [Hxy|Hxy] [Hyz|Hyz].
- left; transitivity y; auto.
- left; rewrite <- Hyz; auto.
- left; rewrite Hxy; auto.
- right; transitivity y; auto.
+ - left; transitivity y; auto.
+ - left; rewrite <- Hyz; auto.
+ - left; rewrite Hxy; auto.
+ - right; transitivity y; auto.
Qed.
Definition t := t.
@@ -302,10 +304,10 @@ Module TTLB_to_OTF (Import O : TotalTransitiveLeBool') <: OrderedTypeFull.
Proof.
intros. unfold compare.
case_eq (x <=? y).
- case_eq (y <=? x).
- constructor. split; auto.
- constructor. split; congruence.
- constructor. destruct (leb_total x y); split; congruence.
+ - case_eq (y <=? x).
+ + constructor. split; auto.
+ + constructor. split; congruence.
+ - constructor. destruct (leb_total x y); split; congruence.
Qed.
Definition eqb x y := (x <=? y) && (y <=? x).
@@ -321,19 +323,19 @@ Module TTLB_to_OTF (Import O : TotalTransitiveLeBool') <: OrderedTypeFull.
Instance eq_equiv : Equivalence eq.
Proof.
split.
- intros x; unfold eq, le. destruct (leb_total x x); auto.
- intros x y; unfold eq, le. intuition.
- intros x y z; unfold eq, le. intuition; apply leb_trans with y; auto.
+ - intros x; unfold eq, le. destruct (leb_total x x); auto.
+ - intros x y; unfold eq, le. intuition.
+ - intros x y z; unfold eq, le. intuition; apply leb_trans with y; auto.
Qed.
Instance lt_strorder : StrictOrder lt.
Proof.
split.
- intros x. unfold lt; red; intuition.
- intros x y z; unfold lt, le. intuition.
- apply leb_trans with y; auto.
- absurd (z <=? y); auto.
- apply leb_trans with x; auto.
+ - intros x. unfold lt; red; intuition.
+ - intros x y z; unfold lt, le. intuition.
+ + apply leb_trans with y; auto.
+ + absurd (z <=? y); auto.
+ apply leb_trans with x; auto.
Qed.
Instance lt_compat : Proper (eq ==> eq ==> iff) lt.
@@ -341,11 +343,11 @@ Module TTLB_to_OTF (Import O : TotalTransitiveLeBool') <: OrderedTypeFull.
apply proper_sym_impl_iff_2; auto with *.
intros x x' Hx y y' Hy' H. unfold eq, lt, le in *.
intuition.
- apply leb_trans with x; auto.
- apply leb_trans with y; auto.
- absurd (y <=? x); auto.
- apply leb_trans with x'; auto.
- apply leb_trans with y'; auto.
+ - apply leb_trans with x; auto.
+ apply leb_trans with y; auto.
+ - absurd (y <=? x); auto.
+ apply leb_trans with x'; auto.
+ apply leb_trans with y'; auto.
Qed.
Definition le_lteq : forall x y, le x y <-> lt x y \/ eq x y.
diff --git a/theories/Structures/OrdersFacts.v b/theories/Structures/OrdersFacts.v
index 1fb0a37e16..182b781fe1 100644
--- a/theories/Structures/OrdersFacts.v
+++ b/theories/Structures/OrdersFacts.v
@@ -290,9 +290,9 @@ Module Type CompareBasedOrderFacts
Lemma compare_spec x y : CompareSpec (x==y) (x<y) (y<x) (x?=y).
Proof.
case_eq (compare x y); intros H; constructor.
- now apply compare_eq_iff.
- now apply compare_lt_iff.
- rewrite compare_antisym, CompOpp_iff in H. now apply compare_lt_iff.
+ - now apply compare_eq_iff.
+ - now apply compare_lt_iff.
+ - rewrite compare_antisym, CompOpp_iff in H. now apply compare_lt_iff.
Qed.
Lemma compare_eq x y : (x ?= y) = Eq -> x==y.
diff --git a/theories/Wellfounded/Disjoint_Union.v b/theories/Wellfounded/Disjoint_Union.v
index 10d9027435..ea7769a994 100644
--- a/theories/Wellfounded/Disjoint_Union.v
+++ b/theories/Wellfounded/Disjoint_Union.v
@@ -45,11 +45,11 @@ Section Wf_Disjoint_Union.
intros.
unfold well_founded.
destruct a as [a| b].
- apply (acc_A_sum a).
- apply (H a).
+ - apply (acc_A_sum a).
+ apply (H a).
- apply (acc_B_sum H b).
- apply (H0 b).
+ - apply (acc_B_sum H b).
+ apply (H0 b).
Qed.
End Wf_Disjoint_Union.
diff --git a/theories/Wellfounded/Lexicographic_Product.v b/theories/Wellfounded/Lexicographic_Product.v
index 37fd2fb23f..b2d08186ea 100644
--- a/theories/Wellfounded/Lexicographic_Product.v
+++ b/theories/Wellfounded/Lexicographic_Product.v
@@ -36,23 +36,23 @@ Section WfLexicographic_Product.
apply Acc_intro.
destruct y as [x2 y1]; intro H6.
simple inversion H6; intro.
- cut (leA x2 x); intros.
- apply IHAcc; auto with sets.
- intros.
- apply H2.
- apply t_trans with x2; auto with sets.
-
- red in H2.
- apply H2.
- auto with sets.
-
- injection H1 as <- _.
- injection H3 as <- _; auto with sets.
-
- rewrite <- H1.
- injection H3 as -> H3.
- apply IHAcc0.
- elim inj_pair2 with A B x y' x0; assumption.
+ - cut (leA x2 x); intros.
+ + apply IHAcc; auto with sets.
+ * intros.
+ apply H2.
+ apply t_trans with x2; auto with sets.
+
+ * red in H2.
+ apply H2.
+ auto with sets.
+
+ + injection H1 as <- _.
+ injection H3 as <- _; auto with sets.
+
+ - rewrite <- H1.
+ injection H3 as -> H3.
+ apply IHAcc0.
+ elim inj_pair2 with A B x y' x0; assumption.
Defined.
Theorem wf_lexprod :
@@ -116,17 +116,17 @@ Section Swap.
apply Acc_intro.
destruct y0; intros.
inversion_clear H; inversion_clear H1; apply H0.
- apply sp_swap.
- apply right_sym; auto with sets.
+ - apply sp_swap.
+ apply right_sym; auto with sets.
- apply sp_swap.
- apply left_sym; auto with sets.
+ - apply sp_swap.
+ apply left_sym; auto with sets.
- apply sp_noswap.
- apply right_sym; auto with sets.
+ - apply sp_noswap.
+ apply right_sym; auto with sets.
- apply sp_noswap.
- apply left_sym; auto with sets.
+ - apply sp_noswap.
+ apply left_sym; auto with sets.
Defined.
@@ -135,26 +135,26 @@ Section Swap.
Proof.
induction 1 as [x0 _ IHAcc0]; intros H2.
cut (forall y0:A, R y0 x0 -> Acc SwapProd (y0, y)).
- clear IHAcc0.
- induction H2 as [x1 _ IHAcc1]; intros H4.
- cut (forall y:A, R y x1 -> Acc SwapProd (x0, y)).
- clear IHAcc1.
- intro.
- apply Acc_intro.
- destruct y; intro H5.
- inversion_clear H5.
- inversion_clear H0; auto with sets.
-
- apply swap_Acc.
- inversion_clear H0; auto with sets.
-
- intros.
- apply IHAcc1; auto with sets; intros.
- apply Acc_inv with (y0, x1); auto with sets.
- apply sp_noswap.
- apply right_sym; auto with sets.
-
- auto with sets.
+ - clear IHAcc0.
+ induction H2 as [x1 _ IHAcc1]; intros H4.
+ cut (forall y:A, R y x1 -> Acc SwapProd (x0, y)).
+ + clear IHAcc1.
+ intro.
+ apply Acc_intro.
+ destruct y; intro H5.
+ inversion_clear H5.
+ * inversion_clear H0; auto with sets.
+
+ * apply swap_Acc.
+ inversion_clear H0; auto with sets.
+
+ + intros.
+ apply IHAcc1; auto with sets; intros.
+ apply Acc_inv with (y0, x1); auto with sets.
+ apply sp_noswap.
+ apply right_sym; auto with sets.
+
+ - auto with sets.
Defined.
diff --git a/theories/Wellfounded/Union.v b/theories/Wellfounded/Union.v
index 9e671651fa..14d425b811 100644
--- a/theories/Wellfounded/Union.v
+++ b/theories/Wellfounded/Union.v
@@ -27,13 +27,13 @@ Section WfUnion.
forall z:A, R2 z y -> exists2 y' : A, R2 y' x & clos_trans A R1 z y'.
Proof.
induction 2 as [x y| x y z H0 IH1 H1 IH2]; intros.
- elim H with y x z; auto with sets; intros x0 H2 H3.
- exists x0; auto with sets.
+ - elim H with y x z; auto with sets; intros x0 H2 H3.
+ exists x0; auto with sets.
- elim IH1 with z0; auto with sets; intros.
- elim IH2 with x0; auto with sets; intros.
- exists x1; auto with sets.
- apply t_trans with x0; auto with sets.
+ - elim IH1 with z0; auto with sets; intros.
+ elim IH2 with x0; auto with sets; intros.
+ exists x1; auto with sets.
+ apply t_trans with x0; auto with sets.
Qed.
@@ -46,21 +46,21 @@ Section WfUnion.
elim H3; intros; auto with sets.
cut (clos_trans A R1 y x); auto with sets.
elimtype (Acc (clos_trans A R1) y); intros.
- apply Acc_intro; intros.
- elim H8; intros.
- apply H6; auto with sets.
- apply t_trans with x0; auto with sets.
+ - apply Acc_intro; intros.
+ elim H8; intros.
+ + apply H6; auto with sets.
+ apply t_trans with x0; auto with sets.
- elim strip_commut with x x0 y0; auto with sets; intros.
- apply Acc_inv_trans with x1; auto with sets.
- unfold union.
- elim H11; auto with sets; intros.
- apply t_trans with y1; auto with sets.
+ + elim strip_commut with x x0 y0; auto with sets; intros.
+ apply Acc_inv_trans with x1; auto with sets.
+ unfold union.
+ elim H11; auto with sets; intros.
+ apply t_trans with y1; auto with sets.
- apply (Acc_clos_trans A).
- apply Acc_inv with x; auto with sets.
- apply H0.
- apply Acc_intro; auto with sets.
+ - apply (Acc_clos_trans A).
+ apply Acc_inv with x; auto with sets.
+ apply H0.
+ apply Acc_intro; auto with sets.
Qed.
diff --git a/theories/Wellfounded/Well_Ordering.v b/theories/Wellfounded/Well_Ordering.v
index cf46657d36..eb98fb2aba 100644
--- a/theories/Wellfounded/Well_Ordering.v
+++ b/theories/Wellfounded/Well_Ordering.v
@@ -39,9 +39,9 @@ Section WellOrdering.
intros.
apply (H v0 y0).
cut (f = f1).
- intros E; rewrite E; auto.
- symmetry .
- apply (inj_pair2 A (fun a0:A => B a0 -> WO) a0 f1 f H5).
+ - intros E; rewrite E; auto.
+ - symmetry .
+ apply (inj_pair2 A (fun a0:A => B a0 -> WO) a0 f1 f H5).
Qed.
End WellOrdering.
diff --git a/tools/coq_dune.ml b/tools/coq_dune.ml
index 9ecd8f19ce..68371edcb1 100644
--- a/tools/coq_dune.ml
+++ b/tools/coq_dune.ml
@@ -186,7 +186,7 @@ let pp_vo_dep dir fmt vo =
(* We explicitly include the location of coqlib to avoid tricky issues with coqlib location *)
let libflag = "-coqlib %{project_root}" in
(* The final build rule *)
- let action = sprintf "(chdir %%{project_root} (run coqtop -boot %s %s %s -compile %s))" libflag eflag cflag source in
+ let action = sprintf "(chdir %%{project_root} (run coqc -boot %s %s %s %s))" libflag eflag cflag source in
let all_targets = gen_coqc_targets vo in
pp_rule fmt all_targets deps action
@@ -271,8 +271,13 @@ let exec_ifile f =
match Array.length Sys.argv with
| 1 -> f stdin
| 2 ->
- let ic = open_in Sys.argv.(1) in
- (try f ic with _ -> close_in ic)
+ let in_file = Sys.argv.(1) in
+ begin try
+ let ic = open_in in_file in
+ (try f ic
+ with _ -> eprintf "Error: exec_ifile@\n%!"; close_in ic)
+ with _ -> eprintf "Error: cannot open input file %s@\n%!" in_file
+ end
| _ -> eprintf "Error: wrong number of arguments@\n%!"; exit 1
let _ =
diff --git a/tools/coqc.ml b/tools/coqc.ml
deleted file mode 100644
index ae841212a7..0000000000
--- a/tools/coqc.ml
+++ /dev/null
@@ -1,163 +0,0 @@
-(************************************************************************)
-(* * The Coq Proof Assistant / The Coq Development Team *)
-(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
-(* <O___,, * (see CREDITS file for the list of authors) *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(* * (see LICENSE file for the text of the license) *)
-(************************************************************************)
-
-(** Coq compiler : coqc *)
-
-(** For improving portability, coqc is now an OCaml program instead
- of a shell script. We use as much as possible the Sys and Filename
- module for better portability, but the Unix module is still used
- here and there (with explicitly qualified function names Unix.foo).
-
- We process here the commmand line to extract names of files to compile,
- then we compile them one by one while passing by the rest of the command
- line to a process running "coqtop -batch -compile <file>".
-*)
-
-(* Environment *)
-
-let environment = Unix.environment ()
-
-let use_bytecode = ref false
-let image = ref ""
-
-let verbose = ref false
-
-let rec make_compilation_args = function
- | [] -> []
- | file :: fl ->
- (if !verbose then "-compile-verbose" else "-compile")
- :: file :: (make_compilation_args fl)
-
-(* compilation of files [files] with command [command] and args [args] *)
-
-let compile command args files =
- let args' = command :: args @ (make_compilation_args files) in
- match Sys.os_type with
- | "Win32" ->
- let pid =
- Unix.create_process_env command (Array.of_list args') environment
- Unix.stdin Unix.stdout Unix.stderr
- in
- let status = snd (Unix.waitpid [] pid) in
- let errcode =
- match status with Unix.WEXITED c|Unix.WSTOPPED c|Unix.WSIGNALED c -> c
- in
- exit errcode
- | _ ->
- Unix.execvpe command (Array.of_list args') environment
-
-let usage () =
- Usage.print_usage_coqc () ;
- flush stderr ;
- exit 1
-
-(* parsing of the command line *)
-let extra_arg_needed = ref true
-
-let parse_args () =
- let rec parse (cfiles,args) = function
- | [] ->
- List.rev cfiles, List.rev args
- | ("-verbose" | "--verbose") :: rem ->
- verbose := true ; parse (cfiles,args) rem
- | "-image" :: f :: rem -> image := f; parse (cfiles,args) rem
- | "-image" :: [] -> usage ()
- | "-byte" :: rem -> use_bytecode := true; parse (cfiles,args) rem
- | "-opt" :: rem -> use_bytecode := false; parse (cfiles,args) rem
-
-(* Informative options *)
-
- | ("-?"|"-h"|"-H"|"-help"|"--help") :: _ -> usage ()
-
- | ("-v"|"--version") :: _ -> Usage.version 0
-
- | ("-where") :: _ ->
- Envars.set_coqlib ~fail:(fun x -> x);
- print_endline (Envars.coqlib ());
- exit 0
-
- | ("-config" | "--config") :: _ ->
- Envars.set_coqlib ~fail:(fun x -> x);
- Envars.print_config stdout Coq_config.all_src_dirs;
- exit 0
-
- | ("-print-version" | "--print-version") :: _ ->
- Usage.machine_readable_version 0
-
-(* Options for coqtop : a) options with 0 argument *)
-
- | ("-bt"|"-debug"|"-nolib"|"-boot"|"-time"|"-profile-ltac"
- |"-batch"|"-noinit"|"-nois"|"-noglob"|"-no-glob"
- |"-q"|"-profile"|"-echo" |"-quiet"
- |"-silent"|"-m"|"-beautify"|"-strict-implicit"
- |"-impredicative-set"|"-vm"
- |"-indices-matter"|"-quick"|"-type-in-type"
- |"-async-proofs-always-delegate"|"-async-proofs-never-reopen-branch"
- |"-stm-debug"
- as o) :: rem ->
- parse (cfiles,o::args) rem
-
-(* Options for coqtop : b) options with 1 argument *)
-
- | ("-outputstate"|"-inputstate"|"-is"|"-exclude-dir"|"-color"
- |"-load-vernac-source"|"-l"|"-load-vernac-object"
- |"-load-ml-source"|"-require"|"-load-ml-object"
- |"-init-file"|"-dump-glob"|"-compat"|"-coqlib"|"-top"|"-topfile"
- |"-async-proofs-j" |"-async-proofs-private-flags" |"-async-proofs" |"-w"
- |"-o"|"-profile-ltac-cutoff"|"-mangle-names"|"-bytecode-compiler"|"-native-compiler"
- as o) :: rem ->
- begin
- match rem with
- | s :: rem' -> parse (cfiles,s::o::args) rem'
- | [] -> usage ()
- end
- | ("-I"|"-include" as o) :: s :: rem -> parse (cfiles,s::o::args) rem
-
-(* Options for coqtop : c) options with 1 argument and possibly more *)
-
- | ("-R"|"-Q" as o) :: s :: t :: rem -> parse (cfiles,t::s::o::args) rem
- | ("-schedule-vio-checking"
- |"-check-vio-tasks" | "-schedule-vio2vo" as o) :: s :: rem ->
- let nodash, rem =
- CList.split_when (fun x -> String.length x > 1 && x.[0] = '-') rem in
- extra_arg_needed := false;
- parse (cfiles, List.rev nodash @ s :: o :: args) rem
-
- | f :: rem ->
- if Sys.file_exists f then
- parse (f::cfiles,args) rem
- else
- let fv = f ^ ".v" in
- if Sys.file_exists fv then
- parse (fv::cfiles,args) rem
- else begin
- prerr_endline ("coqc: "^f^": no such file or directory") ;
- exit 1
- end
- in
- parse ([],[]) (List.tl (Array.to_list Sys.argv))
-
-(* main: we parse the command line, define the command to compile files
- * and then call the compilation on each file *)
-
-let main () =
- let cfiles, args = parse_args () in
- if cfiles = [] && !extra_arg_needed then begin
- prerr_endline "coqc: too few arguments" ;
- usage ()
- end;
- let coqtopname =
- if !image <> "" then !image
- else System.get_toplevel_path ~byte:!use_bytecode "coqtop"
- in
- (* List.iter (compile coqtopname args) cfiles*)
- Unix.handle_unix_error (compile coqtopname args) cfiles
-
-let _ = Printexc.print main ()
diff --git a/tools/dune b/tools/dune
index 31b70fb06c..204bd09535 100644
--- a/tools/dune
+++ b/tools/dune
@@ -16,13 +16,6 @@
(libraries coq.lib))
(executable
- (name coqc)
- (public_name coqc)
- (package coq)
- (modules coqc)
- (libraries coq.toplevel))
-
-(executable
(name coqworkmgr)
(public_name coqworkmgr)
(package coq)
diff --git a/topbin/coqc_bin.ml b/topbin/coqc_bin.ml
new file mode 100644
index 0000000000..d711c81124
--- /dev/null
+++ b/topbin/coqc_bin.ml
@@ -0,0 +1,13 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+(* Main coqc initialization *)
+let _ =
+ Coqc.main ()
diff --git a/topbin/dune b/topbin/dune
index 52f472d149..f42e4d6fc2 100644
--- a/topbin/dune
+++ b/topbin/dune
@@ -20,11 +20,19 @@
(modes byte)
(link_flags -linkall))
+(executable
+ (name coqc_bin)
+ (public_name coqc)
+ (package coq)
+ (modules coqc_bin)
+ (libraries coq.toplevel)
+ (link_flags -linkall))
+
; Workers
(executables
(names coqqueryworker_bin coqtacticworker_bin coqproofworker_bin)
(public_names coqqueryworker.opt coqtacticworker.opt coqproofworker.opt)
(package coq)
- (modules :standard \ coqtop_byte_bin coqtop_bin)
+ (modules :standard \ coqtop_byte_bin coqtop_bin coqc_bin)
(libraries coq.toplevel)
(link_flags -linkall))
diff --git a/toplevel/ccompile.ml b/toplevel/ccompile.ml
index b248b87880..df2b983029 100644
--- a/toplevel/ccompile.ml
+++ b/toplevel/ccompile.ml
@@ -10,6 +10,7 @@
open Pp
open Coqargs
+open Coqcargs
let fatal_error msg =
Topfmt.std_logger Feedback.Error msg;
@@ -81,7 +82,7 @@ let ensure_exists f =
fatal_error (hov 0 (str "Can't find file" ++ spc () ++ str f))
(* Compile a vernac file *)
-let compile opts ~echo ~f_in ~f_out =
+let compile opts copts ~echo ~f_in ~f_out =
let open Vernac.State in
let check_pending_proofs () =
let pfs = Proof_global.get_all_proof_names () in
@@ -95,7 +96,7 @@ let compile opts ~echo ~f_in ~f_out =
let iload_path = build_load_path opts in
let require_libs = require_libs opts in
let stm_options = opts.stm_flags in
- match opts.compilation_mode with
+ match copts.compilation_mode with
| BuildVo ->
Flags.record_aux_file := true;
let long_f_dot_v = ensure_v f_in in
@@ -179,47 +180,47 @@ let compile opts ~echo ~f_in ~f_out =
let univs, proofs = Stm.finish_tasks lfdv univs disch proofs tasks in
Library.save_library_raw lfdv sum lib univs proofs
-let compile opts ~echo ~f_in ~f_out =
+let compile opts copts ~echo ~f_in ~f_out =
ignore(CoqworkmgrApi.get 1);
- compile opts ~echo ~f_in ~f_out;
+ compile opts copts ~echo ~f_in ~f_out;
CoqworkmgrApi.giveback 1
-let compile_file opts (f_in, echo) =
- let f_out = opts.compilation_output_name in
+let compile_file opts copts (f_in, echo) =
+ let f_out = copts.compilation_output_name in
if !Flags.beautify then
Flags.with_option Flags.beautify_file
- (fun f_in -> compile opts ~echo ~f_in ~f_out) f_in
+ (fun f_in -> compile opts copts ~echo ~f_in ~f_out) f_in
else
- compile opts ~echo ~f_in ~f_out
+ compile opts copts ~echo ~f_in ~f_out
-let compile_files opts =
- let compile_list = List.rev opts.compile_list in
- List.iter (compile_file opts) compile_list
+let compile_files opts copts =
+ let compile_list = List.rev copts.compile_list in
+ List.iter (compile_file opts copts) compile_list
(******************************************************************************)
(* VIO Dispatching *)
(******************************************************************************)
-let check_vio_tasks opts =
+let check_vio_tasks copts =
let rc =
List.fold_left (fun acc t -> Vio_checking.check_vio t && acc)
- true (List.rev opts.vio_tasks) in
+ true (List.rev copts.vio_tasks) in
if not rc then fatal_error Pp.(str "VIO Task Check failed")
(* vio files *)
-let schedule_vio opts =
- if opts.vio_checking then
- Vio_checking.schedule_vio_checking opts.vio_files_j opts.vio_files
+let schedule_vio copts =
+ if copts.vio_checking then
+ Vio_checking.schedule_vio_checking copts.vio_files_j copts.vio_files
else
- Vio_checking.schedule_vio_compilation opts.vio_files_j opts.vio_files
+ Vio_checking.schedule_vio_compilation copts.vio_files_j copts.vio_files
-let do_vio opts =
+let do_vio opts copts =
(* We must initialize the loadpath here as the vio scheduling
process happens outside of the STM *)
- if opts.vio_files <> [] || opts.vio_tasks <> [] then
+ if copts.vio_files <> [] || copts.vio_tasks <> [] then
let iload_path = build_load_path opts in
List.iter Mltop.add_coq_path iload_path;
(* Vio compile pass *)
- if opts.vio_files <> [] then schedule_vio opts;
+ if copts.vio_files <> [] then schedule_vio copts;
(* Vio task pass *)
- if opts.vio_tasks <> [] then check_vio_tasks opts
+ if copts.vio_tasks <> [] then check_vio_tasks copts
diff --git a/toplevel/ccompile.mli b/toplevel/ccompile.mli
index 757c91c408..29a76eb966 100644
--- a/toplevel/ccompile.mli
+++ b/toplevel/ccompile.mli
@@ -10,10 +10,10 @@
(** [load_init_vernaculars opts ~state] Load vernaculars from
the init (rc) file *)
-val load_init_vernaculars : Coqargs.coq_cmdopts -> state:Vernac.State.t-> Vernac.State.t
+val load_init_vernaculars : Coqargs.t -> state:Vernac.State.t-> Vernac.State.t
(** [compile_files opts] compile files specified in [opts] *)
-val compile_files : Coqargs.coq_cmdopts -> unit
+val compile_files : Coqargs.t -> Coqcargs.t -> unit
(** [do_vio opts] process [.vio] files in [opts] *)
-val do_vio : Coqargs.coq_cmdopts -> unit
+val do_vio : Coqargs.t -> Coqcargs.t -> unit
diff --git a/toplevel/coqargs.ml b/toplevel/coqargs.ml
index 0a32879764..74c016101a 100644
--- a/toplevel/coqargs.ml
+++ b/toplevel/coqargs.ml
@@ -31,10 +31,9 @@ let set_type_in_type () =
(******************************************************************************)
-type compilation_mode = BuildVo | BuildVio | Vio2Vo
type color = [`ON | `AUTO | `OFF]
-type coq_cmdopts = {
+type t = {
load_init : bool;
load_rcfile : bool;
@@ -45,21 +44,10 @@ type coq_cmdopts = {
vo_requires : (string * string option * bool option) list;
(* None = No Import; Some false = Import; Some true = Export *)
- (* XXX: Fusion? *)
- batch_mode : bool;
- compilation_mode : compilation_mode;
-
toplevel_name : Stm.interactive_top;
- compile_list: (string * bool) list; (* bool is verbosity *)
- compilation_output_name : string option;
-
load_vernacular_list : (string * bool) list;
-
- vio_checking: bool;
- vio_tasks : (int list * string) list;
- vio_files : string list;
- vio_files_j : int;
+ batch : bool;
color : color;
@@ -67,6 +55,7 @@ type coq_cmdopts = {
indices_matter : bool;
enable_VM : bool;
enable_native_compiler : bool;
+
stm_flags : Stm.AsyncOpts.stm_opt;
debug : bool;
diffs_set : bool;
@@ -85,13 +74,12 @@ type coq_cmdopts = {
print_emacs : bool;
inputstate : string option;
- outputstate : string option;
}
let default_toplevel = Names.(DirPath.make [Id.of_string "Top"])
-let default_opts = {
+let default = {
load_init = true;
load_rcfile = true;
@@ -101,20 +89,10 @@ let default_opts = {
vo_includes = [];
vo_requires = [];
- batch_mode = false;
- compilation_mode = BuildVo;
-
toplevel_name = Stm.TopLogical default_toplevel;
- compile_list = [];
- compilation_output_name = None;
-
load_vernacular_list = [];
-
- vio_checking = false;
- vio_tasks = [];
- vio_files = [];
- vio_files_j = 0;
+ batch = false;
color = `AUTO;
@@ -142,7 +120,6 @@ let default_opts = {
(* Quiet / verbosity options should be here *)
inputstate = None;
- outputstate = None;
}
(******************************************************************************)
@@ -165,46 +142,12 @@ let add_compat_require opts v =
match v with
| Flags.V8_7 -> add_vo_require opts "Coq.Compat.Coq87" None (Some false)
| Flags.V8_8 -> add_vo_require opts "Coq.Compat.Coq88" None (Some false)
- | Flags.Current -> add_vo_require opts "Coq.Compat.Coq89" None (Some false)
-
-let set_batch_mode opts =
- (* XXX: This should be in the argument record *)
- Flags.quiet := true;
- System.trust_file_cache := true;
- { opts with batch_mode = true }
-
-let add_compile opts verbose s =
- let opts = set_batch_mode opts in
- if not opts.glob_opt then Dumpglob.dump_to_dotglob ();
- (* make the file name explicit; needed not to break up Coq loadpath stuff. *)
- let s =
- let open Filename in
- if is_implicit s
- then concat current_dir_name s
- else s
- in
- { opts with compile_list = (s,verbose) :: opts.compile_list }
+ | Flags.V8_9 -> add_vo_require opts "Coq.Compat.Coq89" None (Some false)
+ | Flags.Current -> add_vo_require opts "Coq.Compat.Coq810" None (Some false)
let add_load_vernacular opts verb s =
{ opts with load_vernacular_list = (CUnix.make_suffix s ".v",verb) :: opts.load_vernacular_list }
-let add_vio_task opts f =
- let opts = set_batch_mode opts in
- { opts with vio_tasks = f :: opts.vio_tasks }
-
-let add_vio_file opts f =
- let opts = set_batch_mode opts in
- { opts with vio_files = f :: opts.vio_files }
-
-let set_vio_checking_j opts opt j =
- try { opts with vio_files_j = int_of_string j }
- with Failure _ ->
- prerr_endline ("The first argument of " ^ opt ^ " must the number");
- prerr_endline "of concurrent workers to be used (a positive integer).";
- prerr_endline "Makefiles generated by coq_makefile should be called";
- prerr_endline "setting the J variable like in 'make vio2vo J=3'";
- exit 1
-
(** Options for proof general *)
let set_emacs opts =
Printer.enable_goal_tags_printing := true;
@@ -224,22 +167,11 @@ let set_inputstate opts s =
warn_deprecated_inputstate ();
{ opts with inputstate = Some s }
-let warn_deprecated_outputstate =
- CWarnings.create ~name:"deprecated-outputstate" ~category:"deprecated"
- (fun () ->
- Pp.strbrk "The outputstate option is deprecated and discouraged.")
-
-let set_outputstate opts s =
- warn_deprecated_outputstate ();
- { opts with outputstate = Some s }
-
let exitcode opts = if opts.filter_opts then 2 else 0
(******************************************************************************)
(* Parsing helpers *)
(******************************************************************************)
-let get_task_list s = List.map int_of_string (Str.split (Str.regexp ",") s)
-
let get_bool opt = function
| "yes" | "on" -> true
| "no" | "off" -> false
@@ -284,16 +216,6 @@ let get_cache opt = function
| "force" -> Some Stm.AsyncOpts.Force
| _ -> prerr_endline ("Error: force expected after "^opt); exit 1
-let is_not_dash_option = function
- | Some f when String.length f > 0 && f.[0] <> '-' -> true
- | _ -> false
-
-let rec add_vio_args peek next oval =
- if is_not_dash_option (peek ()) then
- let oval = add_vio_file oval (next ()) in
- add_vio_args peek next oval
- else oval
-
let get_native_name s =
(* We ignore even critical errors because this mode has to be super silent *)
try
@@ -310,7 +232,7 @@ let usage_no_coqlib = CWarnings.create ~name:"usage-no-coqlib" ~category:"filesy
exception NoCoqLib
-let usage batch =
+let usage help =
begin
try Envars.set_coqlib ~fail:(fun x -> raise NoCoqLib)
with NoCoqLib -> usage_no_coqlib ()
@@ -318,12 +240,10 @@ let usage batch =
let lp = Coqinit.toplevel_init_load_path () in
(* Necessary for finding the toplevels below *)
List.iter Mltop.add_coq_path lp;
- if batch
- then Usage.print_usage_coqc ()
- else Usage.print_usage_coqtop ()
+ help ()
(* Main parsing routine *)
-let parse_args init_opts arglist : coq_cmdopts * string list =
+let parse_args ~help ~init arglist : t * string list =
let args = ref arglist in
let extras = ref [] in
let rec parse oval = match !args with
@@ -335,10 +255,6 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
| x::rem -> args := rem; x
| [] -> error_missing_arg opt
in
- let peek_next () = match !args with
- | x::_ -> Some x
- | [] -> None
- in
let noval = begin match opt with
(* Complex options with many args *)
@@ -364,23 +280,6 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
| _ -> error_missing_arg opt
end
- (* Options with two arg *)
- |"-check-vio-tasks" ->
- let tno = get_task_list (next ()) in
- let tfile = next () in
- add_vio_task oval (tno,tfile)
-
- |"-schedule-vio-checking" ->
- let oval = { oval with vio_checking = true } in
- let oval = set_vio_checking_j oval opt (next ()) in
- let oval = add_vio_file oval (next ()) in
- add_vio_args peek_next next oval
-
- |"-schedule-vio2vo" ->
- let oval = set_vio_checking_j oval opt (next ()) in
- let oval = add_vio_file oval (next ()) in
- add_vio_args peek_next next oval
-
(* Options with one arg *)
|"-coqlib" ->
Envars.set_user_coqlib (next ());
@@ -435,12 +334,6 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
Flags.compat_version := v;
add_compat_require oval v
- |"-compile" ->
- add_compile oval false (next ())
-
- |"-compile-verbose" ->
- add_compile oval true (next ())
-
|"-dump-glob" ->
Dumpglob.dump_into_file (next ());
{ oval with glob_opt = true }
@@ -457,9 +350,6 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
|"-inputstate"|"-is" ->
set_inputstate oval (next ())
- |"-outputstate" ->
- set_outputstate oval (next ())
-
|"-load-ml-object" ->
Mltop.dir_ml_load (next ()); oval
@@ -505,10 +395,6 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
|"-control-channel" ->
Spawned.control_channel := get_host_port opt (next()); oval
- |"-vio2vo" ->
- let oval = add_compile oval false (next ()) in
- { oval with compilation_mode = Vio2Vo }
-
|"-w" | "-W" ->
let w = next () in
if w = "none" then
@@ -518,8 +404,6 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
CWarnings.set_flags (CWarnings.normalize_flags_string w);
oval
- |"-o" -> { oval with compilation_output_name = Some (next()) }
-
|"-bytecode-compiler" ->
{ oval with enable_VM = get_bool opt (next ()) }
@@ -547,7 +431,9 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
{ oval with stm_flags = { oval.stm_flags with
Stm.AsyncOpts.async_proofs_never_reopen_branch = true
}}
- |"-batch" -> set_batch_mode oval
+ |"-batch" ->
+ Flags.quiet := true;
+ { oval with batch = true }
|"-test-mode" -> Flags.test_mode := true; oval
|"-beautify" -> Flags.beautify := true; oval
|"-boot" -> Flags.boot := true; { oval with load_rcfile = false; }
@@ -577,13 +463,12 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
Flags.quiet := true;
Flags.make_warn false;
oval
- |"-quick" -> { oval with compilation_mode = BuildVio }
|"-list-tags" -> { oval with print_tags = true }
|"-time" -> { oval with time = true }
|"-type-in-type" -> set_type_in_type (); oval
|"-unicode" -> add_vo_require oval "Utf8_core" None (Some false)
|"-where" -> { oval with print_where = true }
- |"-h"|"-H"|"-?"|"-help"|"--help" -> usage oval.batch_mode; oval
+ |"-h"|"-H"|"-?"|"-help"|"--help" -> usage help; oval
|"-v"|"--version" -> Usage.version (exitcode oval)
|"-print-version"|"--print-version" ->
Usage.machine_readable_version (exitcode oval)
@@ -596,13 +481,13 @@ let parse_args init_opts arglist : coq_cmdopts * string list =
parse noval
in
try
- parse init_opts
+ parse init
with any -> fatal_error any
(******************************************************************************)
(* Startup LoadPath and Modules *)
(******************************************************************************)
-(* prelude_data == From Coq Require Export Prelude. *)
+(* prelude_data == From Coq Require Import Prelude. *)
let prelude_data = "Prelude", Some "Coq", Some false
let require_libs opts =
diff --git a/toplevel/coqargs.mli b/toplevel/coqargs.mli
index e645b0c126..c9a7a0fd56 100644
--- a/toplevel/coqargs.mli
+++ b/toplevel/coqargs.mli
@@ -8,12 +8,11 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
-type compilation_mode = BuildVo | BuildVio | Vio2Vo
type color = [`ON | `AUTO | `OFF]
val default_toplevel : Names.DirPath.t
-type coq_cmdopts = {
+type t = {
load_init : bool;
load_rcfile : bool;
@@ -23,22 +22,10 @@ type coq_cmdopts = {
vo_includes : Mltop.coq_path list;
vo_requires : (string * string option * bool option) list;
- (* Fuse these two? Currently, [batch_mode] is only used to
- distinguish coqc / coqtop in help display. *)
- batch_mode : bool;
- compilation_mode : compilation_mode;
-
toplevel_name : Stm.interactive_top;
- compile_list: (string * bool) list; (* bool is verbosity *)
- compilation_output_name : string option;
-
load_vernacular_list : (string * bool) list;
-
- vio_checking: bool;
- vio_tasks : (int list * string) list;
- vio_files : string list;
- vio_files_j : int;
+ batch : bool;
color : color;
@@ -63,18 +50,14 @@ type coq_cmdopts = {
print_emacs : bool;
- (* Quiet / verbosity options should be here *)
-
inputstate : string option;
- outputstate : string option;
-
}
(* Default options *)
-val default_opts : coq_cmdopts
+val default : t
-val parse_args : coq_cmdopts -> string list -> coq_cmdopts * string list
-val exitcode : coq_cmdopts -> int
+val parse_args : help:(unit -> unit) -> init:t -> string list -> t * string list
+val exitcode : t -> int
-val require_libs : coq_cmdopts -> (string * string option * bool option) list
-val build_load_path : coq_cmdopts -> Mltop.coq_path list
+val require_libs : t -> (string * string option * bool option) list
+val build_load_path : t -> Mltop.coq_path list
diff --git a/toplevel/coqc.ml b/toplevel/coqc.ml
new file mode 100644
index 0000000000..d4107177a7
--- /dev/null
+++ b/toplevel/coqc.ml
@@ -0,0 +1,67 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+let set_noninteractive_mode () =
+ Flags.quiet := true;
+ System.trust_file_cache := true
+
+let outputstate opts =
+ Option.iter (fun ostate_file ->
+ let fname = CUnix.make_suffix ostate_file ".coq" in
+ States.extern_state fname) opts.Coqcargs.outputstate
+
+let coqc_main () =
+ (* Careful because init_toplevel will call Summary.init_summaries,
+ thus options such as `quiet` have to be set after the main
+ initialisation is run. *)
+ let coqc_init ~opts args =
+ set_noninteractive_mode ();
+ let opts, args = Coqtop.(coqtop_toplevel.init) ~opts args in
+ opts, args
+ in
+ let opts, extras =
+ Topfmt.(in_phase ~phase:Initialization)
+ Coqtop.(init_toplevel ~help:Usage.print_usage_coqc ~init:Coqargs.default coqc_init) List.(tl (Array.to_list Sys.argv)) in
+
+ let copts = Coqcargs.parse extras in
+
+ if not opts.Coqargs.glob_opt then Dumpglob.dump_to_dotglob ();
+
+ Topfmt.(in_phase ~phase:CompilationPhase)
+ Ccompile.compile_files opts copts;
+
+ (* Careful this will modify the load-path and state so after this
+ point some stuff may not be safe anymore. *)
+ Topfmt.(in_phase ~phase:CompilationPhase)
+ Ccompile.do_vio opts copts;
+
+ (* Allow the user to output an arbitrary state *)
+ outputstate copts;
+
+ flush_all();
+ if opts.Coqargs.output_context then begin
+ let sigma, env = Pfedit.get_current_context () in
+ Feedback.msg_notice Pp.(Flags.(with_option raw_print (Prettyp.print_full_pure_context env) sigma) ++ fnl ())
+ end;
+ CProfile.print_profile ()
+
+let main () =
+ let _feeder = Feedback.add_feeder Coqloop.coqloop_feed in
+ try
+ coqc_main ();
+ exit 0
+ with exn ->
+ flush_all();
+ Topfmt.print_err_exn exn;
+ flush_all();
+ let exit_code =
+ if CErrors.(is_anomaly exn || not (handled exn)) then 129 else 1
+ in
+ exit exit_code
diff --git a/toplevel/coqc.mli b/toplevel/coqc.mli
new file mode 100644
index 0000000000..6049c5e188
--- /dev/null
+++ b/toplevel/coqc.mli
@@ -0,0 +1,11 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+val main : unit -> unit
diff --git a/toplevel/coqcargs.ml b/toplevel/coqcargs.ml
new file mode 100644
index 0000000000..7445619d26
--- /dev/null
+++ b/toplevel/coqcargs.ml
@@ -0,0 +1,174 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+type compilation_mode = BuildVo | BuildVio | Vio2Vo
+
+type t =
+ { compilation_mode : compilation_mode
+
+ ; compile_list: (string * bool) list (* bool is verbosity *)
+ ; compilation_output_name : string option
+
+ ; vio_checking : bool
+ ; vio_tasks : (int list * string) list
+ ; vio_files : string list
+ ; vio_files_j : int
+
+ ; echo : bool
+
+ ; outputstate : string option;
+ }
+
+let default =
+ { compilation_mode = BuildVo
+
+ ; compile_list = []
+ ; compilation_output_name = None
+
+ ; vio_checking = false
+ ; vio_tasks = []
+ ; vio_files = []
+ ; vio_files_j = 0
+
+ ; echo = false
+
+ ; outputstate = None
+ }
+
+let depr opt =
+ Feedback.msg_warning Pp.(seq[str "Option "; str opt; str " is a noop and deprecated"])
+
+(* XXX Remove this duplication with Coqargs *)
+let fatal_error exn =
+ Topfmt.(in_phase ~phase:ParsingCommandLine print_err_exn exn);
+ let exit_code = if CErrors.(is_anomaly exn || not (handled exn)) then 129 else 1 in
+ exit exit_code
+
+let error_missing_arg s =
+ prerr_endline ("Error: extra argument expected after option "^s);
+ prerr_endline "See -help for the syntax of supported options";
+ exit 1
+
+let add_compile ?echo copts s =
+ (* make the file name explicit; needed not to break up Coq loadpath stuff. *)
+ let echo = Option.default copts.echo echo in
+ let s =
+ let open Filename in
+ if is_implicit s
+ then concat current_dir_name s
+ else s
+ in
+ { copts with compile_list = (s,echo) :: copts.compile_list }
+
+let add_vio_task opts f =
+ { opts with vio_tasks = f :: opts.vio_tasks }
+
+let add_vio_file opts f =
+ { opts with vio_files = f :: opts.vio_files }
+
+let set_vio_checking_j opts opt j =
+ try { opts with vio_files_j = int_of_string j }
+ with Failure _ ->
+ prerr_endline ("The first argument of " ^ opt ^ " must the number");
+ prerr_endline "of concurrent workers to be used (a positive integer).";
+ prerr_endline "Makefiles generated by coq_makefile should be called";
+ prerr_endline "setting the J variable like in 'make vio2vo J=3'";
+ exit 1
+
+let get_task_list s = List.map int_of_string (Str.split (Str.regexp ",") s)
+
+let is_not_dash_option = function
+ | Some f when String.length f > 0 && f.[0] <> '-' -> true
+ | _ -> false
+
+let rec add_vio_args peek next oval =
+ if is_not_dash_option (peek ()) then
+ let oval = add_vio_file oval (next ()) in
+ add_vio_args peek next oval
+ else oval
+
+let warn_deprecated_outputstate =
+ CWarnings.create ~name:"deprecated-outputstate" ~category:"deprecated"
+ (fun () ->
+ Pp.strbrk "The outputstate option is deprecated and discouraged.")
+
+let set_outputstate opts s =
+ warn_deprecated_outputstate ();
+ { opts with outputstate = Some s }
+
+let parse arglist : t =
+ let echo = ref false in
+ let args = ref arglist in
+ let extras = ref [] in
+ let rec parse (oval : t) = match !args with
+ | [] ->
+ (oval, List.rev !extras)
+ | opt :: rem ->
+ args := rem;
+ let next () = match !args with
+ | x::rem -> args := rem; x
+ | [] -> error_missing_arg opt
+ in
+ let peek_next () = match !args with
+ | x::_ -> Some x
+ | [] -> None
+ in
+ let noval : t = begin match opt with
+ (* Deprecated options *)
+ | "-opt"
+ | "-byte" as opt ->
+ depr opt;
+ oval
+ | "-image" as opt ->
+ depr opt;
+ let _ = next () in
+ oval
+ (* Verbose == echo mode *)
+ | "-verbose" ->
+ echo := true;
+ oval
+ (* Output filename *)
+ | "-o" ->
+ { oval with compilation_output_name = Some (next ()) }
+ | "-quick" ->
+ { oval with compilation_mode = BuildVio }
+ | "-check-vio-tasks" ->
+ let tno = get_task_list (next ()) in
+ let tfile = next () in
+ add_vio_task oval (tno,tfile)
+
+ | "-schedule-vio-checking" ->
+ let oval = { oval with vio_checking = true } in
+ let oval = set_vio_checking_j oval opt (next ()) in
+ let oval = add_vio_file oval (next ()) in
+ add_vio_args peek_next next oval
+
+ | "-schedule-vio2vo" ->
+ let oval = set_vio_checking_j oval opt (next ()) in
+ let oval = add_vio_file oval (next ()) in
+ add_vio_args peek_next next oval
+
+ | "-vio2vo" ->
+ let oval = add_compile ~echo:false oval (next ()) in
+ { oval with compilation_mode = Vio2Vo }
+
+ | "-outputstate" ->
+ set_outputstate oval (next ())
+
+ | s ->
+ extras := s :: !extras;
+ oval
+ end in
+ parse noval
+ in
+ try
+ let opts, extra = parse default in
+ List.fold_left add_compile opts extra
+ with any -> fatal_error any
diff --git a/toplevel/coqcargs.mli b/toplevel/coqcargs.mli
new file mode 100644
index 0000000000..7792056b24
--- /dev/null
+++ b/toplevel/coqcargs.mli
@@ -0,0 +1,30 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+type compilation_mode = BuildVo | BuildVio | Vio2Vo
+
+type t =
+ { compilation_mode : compilation_mode
+
+ ; compile_list: (string * bool) list (* bool is verbosity *)
+ ; compilation_output_name : string option
+
+ ; vio_checking : bool
+ ; vio_tasks : (int list * string) list
+ ; vio_files : string list
+ ; vio_files_j : int
+
+ ; echo : bool
+
+ ; outputstate : string option
+ }
+
+val default : t
+val parse : string list -> t
diff --git a/toplevel/coqloop.ml b/toplevel/coqloop.ml
index e58b9ccac7..cdbe444e5b 100644
--- a/toplevel/coqloop.ml
+++ b/toplevel/coqloop.ml
@@ -243,7 +243,7 @@ let set_prompt prompt =
let parse_to_dot =
let rec dot st = match Stream.next st with
| Tok.KEYWORD ("."|"...") -> ()
- | Tok.EOI -> raise Stm.End_of_input
+ | Tok.EOI -> ()
| _ -> dot st
in
Pcoq.Entry.of_parser "Coqtoplevel.dot" dot
@@ -257,12 +257,12 @@ let rec discard_to_dot () =
Pcoq.Entry.parse parse_to_dot top_buffer.tokens
with
| Gramlib.Plexing.Error _ | CLexer.Error.E _ -> discard_to_dot ()
- | Stm.End_of_input -> raise Stm.End_of_input
| e when CErrors.noncritical e -> ()
let read_sentence ~state input =
(* XXX: careful with ignoring the state Eugene!*)
- try G_toplevel.parse_toplevel input
+ let open Vernac.State in
+ try Stm.parse_sentence ~doc:state.doc state.sid ~entry:G_toplevel.vernac_toplevel input
with reraise ->
let reraise = CErrors.push reraise in
discard_to_dot ();
@@ -366,7 +366,6 @@ let top_goal_print ~doc c oldp newp =
let msg = CErrors.iprint (e, info) in
TopErr.print_error_for_buffer ?loc Feedback.Error msg top_buffer
-(* Careful to keep this loop tail-rec *)
let rec vernac_loop ~state =
let open CAst in
let open Vernac.State in
@@ -379,26 +378,30 @@ let rec vernac_loop ~state =
try
let input = top_buffer.tokens in
match read_sentence ~state input with
- | {v=VernacBacktrack(bid,_,_)} ->
+ | Some { v = VernacBacktrack(bid,_,_) } ->
let bid = Stateid.of_int bid in
let doc, res = Stm.edit_at ~doc:state.doc bid in
assert (res = `NewTip);
let state = { state with doc; sid = bid } in
vernac_loop ~state
- | {v=VernacQuit} ->
+ | Some { v = VernacQuit } ->
exit 0
- | {v=VernacDrop} ->
+
+ | Some { v = VernacDrop } ->
if Mltop.is_ocaml_top()
then (drop_last_doc := Some state; state)
else (Feedback.msg_warning (str "There is no ML toplevel."); vernac_loop ~state)
- | {v=VernacControl c; loc} ->
+
+ | Some { v = VernacControl c; loc } ->
let nstate = Vernac.process_expr ~state (make ?loc c) in
top_goal_print ~doc:state.doc c state.proof nstate.proof;
vernac_loop ~state:nstate
+
+ | None ->
+ top_stderr (fnl ()); exit 0
+
with
- | Stm.End_of_input ->
- top_stderr (fnl ()); exit 0
(* Exception printing should be done by the feedback listener,
however this is not yet ready so we rely on the exception for
now. *)
diff --git a/toplevel/coqloop.mli b/toplevel/coqloop.mli
index 7d03484412..0cc22ba31d 100644
--- a/toplevel/coqloop.mli
+++ b/toplevel/coqloop.mli
@@ -31,7 +31,7 @@ val coqloop_feed : Feedback.feedback -> unit
(** Last document seen after `Drop` *)
val drop_last_doc : Vernac.State.t option ref
-val drop_args : Coqargs.coq_cmdopts option ref
+val drop_args : Coqargs.t option ref
(** Main entry point of Coq: read and execute vernac commands. *)
-val loop : opts:Coqargs.coq_cmdopts -> state:Vernac.State.t -> unit
+val loop : opts:Coqargs.t -> state:Vernac.State.t -> unit
diff --git a/toplevel/coqtop.ml b/toplevel/coqtop.ml
index 56622abc92..6ef0aa390d 100644
--- a/toplevel/coqtop.ml
+++ b/toplevel/coqtop.ml
@@ -58,11 +58,6 @@ let inputstate opts =
let fname = Loadpath.locate_file (CUnix.make_suffix istate_file ".coq") in
States.intern_state fname) opts.inputstate
-let outputstate opts =
- Option.iter (fun ostate_file ->
- let fname = CUnix.make_suffix ostate_file ".coq" in
- States.extern_state fname) opts.outputstate
-
(******************************************************************************)
(* Fatal Errors *)
(******************************************************************************)
@@ -102,7 +97,7 @@ let init_color opts =
else
false
in
- if Proof_diffs.show_diffs () && not term_color && not opts.batch_mode then
+ if Proof_diffs.show_diffs () && not term_color then
(prerr_endline "Error: -diffs requires enabling -color"; exit 1);
Topfmt.init_terminal_output ~color:term_color
@@ -148,116 +143,114 @@ let init_gc () =
Gc.space_overhead = 120}
(** Main init routine *)
-let init_toplevel init_opts custom_init arglist =
+let init_toplevel ~help ~init custom_init arglist =
(* Coq's init process, phase 1:
OCaml parameters, basic structures, and IO
*)
CProfile.init_profile ();
init_gc ();
Sys.catch_break false; (* Ctrl-C is fatal during the initialisation *)
- let init_feeder = Feedback.add_feeder Coqloop.coqloop_feed in
Lib.init();
(* Coq's init process, phase 2:
Basic Coq environment, load-path, plugins.
*)
- let res = begin
- try
- let opts,extras = parse_args init_opts arglist in
- memory_stat := opts.memory_stat;
-
- (* If we have been spawned by the Spawn module, this has to be done
- * early since the master waits us to connect back *)
- Spawned.init_channels ();
- Envars.set_coqlib ~fail:(fun msg -> CErrors.user_err Pp.(str msg));
- if opts.print_where then begin
- print_endline (Envars.coqlib ());
- exit (exitcode opts)
- end;
- if opts.print_config then begin
- Envars.print_config stdout Coq_config.all_src_dirs;
- exit (exitcode opts)
- end;
- if opts.print_tags then begin
- print_style_tags opts;
- exit (exitcode opts)
- end;
- if opts.filter_opts then begin
- print_string (String.concat "\n" extras);
- exit 0;
- end;
- let top_lp = Coqinit.toplevel_init_load_path () in
- List.iter Mltop.add_coq_path top_lp;
- let opts, extras = custom_init ~opts extras in
- if not (CList.is_empty extras) then begin
- prerr_endline ("Don't know what to do with "^String.concat " " extras);
- prerr_endline "See -help for the list of supported options";
- exit 1
- end;
- Flags.if_verbose print_header ();
- Mltop.init_known_plugins ();
- Global.set_engagement opts.impredicative_set;
- Global.set_indices_matter opts.indices_matter;
- Global.set_VM opts.enable_VM;
- Global.set_native_compiler opts.enable_native_compiler;
-
- (* Allow the user to load an arbitrary state here *)
- inputstate opts;
-
- (* This state will be shared by all the documents *)
- Stm.init_core ();
-
- (* Coq init process, phase 3: Stm initialization, backtracking state.
-
- It is essential that the module system is in a consistent
- state before we take the first snapshot. This was not
- guaranteed in the past, but now is thanks to the STM API.
-
- We split the codepath here depending whether coqtop is called
- in interactive mode or not. *)
-
- (* The condition for starting the interactive mode is a bit
- convoluted, we should really refactor batch/compilation_mode
- more. *)
- if (not opts.batch_mode
- || CList.(is_empty opts.compile_list && is_empty opts.vio_files && is_empty opts.vio_tasks))
- (* Interactive *)
- then begin
- let iload_path = build_load_path opts in
- let require_libs = require_libs opts in
- let stm_options = opts.stm_flags in
- let open Vernac.State in
- let doc, sid = Topfmt.(in_phase ~phase:LoadingPrelude)
- Stm.new_doc
- Stm.{ doc_type = Interactive opts.toplevel_name;
- iload_path; require_libs; stm_options;
- } in
- let state = { doc; sid; proof = None; time = opts.time } in
- Some (Ccompile.load_init_vernaculars opts ~state), opts
- (* Non interactive: we perform a sequence of compilation steps *)
- end else begin
- Ccompile.compile_files opts;
- (* Careful this will modify the load-path and state so after
- this point some stuff may not be safe anymore. *)
- Ccompile.do_vio opts;
- (* Allow the user to output an arbitrary state *)
- outputstate opts;
- None, opts
- end;
- with any ->
- flush_all();
- fatal_error_exn any
- end in
- Feedback.del_feeder init_feeder;
- res
+ let opts, extras = parse_args ~help ~init arglist in
+ memory_stat := opts.memory_stat;
+
+ (* If we have been spawned by the Spawn module, this has to be done
+ * early since the master waits us to connect back *)
+ Spawned.init_channels ();
+ Envars.set_coqlib ~fail:(fun msg -> CErrors.user_err Pp.(str msg));
+ if opts.print_where then begin
+ print_endline (Envars.coqlib ());
+ exit (exitcode opts)
+ end;
+ if opts.print_config then begin
+ Envars.print_config stdout Coq_config.all_src_dirs;
+ exit (exitcode opts)
+ end;
+ if opts.print_tags then begin
+ print_style_tags opts;
+ exit (exitcode opts)
+ end;
+ if opts.filter_opts then begin
+ print_string (String.concat "\n" extras);
+ exit 0;
+ end;
+ let top_lp = Coqinit.toplevel_init_load_path () in
+ List.iter Mltop.add_coq_path top_lp;
+ let opts, extras = custom_init ~opts extras in
+ Flags.if_verbose print_header ();
+ Mltop.init_known_plugins ();
+
+ Global.set_engagement opts.impredicative_set;
+ Global.set_indices_matter opts.indices_matter;
+ Global.set_VM opts.enable_VM;
+ Global.set_native_compiler opts.enable_native_compiler;
+
+ (* Allow the user to load an arbitrary state here *)
+ inputstate opts;
+
+ (* This state will be shared by all the documents *)
+ Stm.init_core ();
+
+ (* Coq init process, phase 3: Stm initialization, backtracking state.
+
+ It is essential that the module system is in a consistent
+ state before we take the first snapshot. This was not
+ guaranteed in the past, but now is thanks to the STM API.
+ *)
+ opts, extras
+
+type init_fn = opts:Coqargs.t -> string list -> Coqargs.t * string list
type custom_toplevel =
- { init : opts:coq_cmdopts -> string list -> coq_cmdopts * string list
- ; run : opts:coq_cmdopts -> state:Vernac.State.t -> unit
- ; opts : Coqargs.coq_cmdopts
+ { init : init_fn
+ ; run : opts:Coqargs.t -> state:Vernac.State.t -> unit
+ ; opts : Coqargs.t
}
+
+let init_toploop opts =
+ let iload_path = build_load_path opts in
+ let require_libs = require_libs opts in
+ let stm_options = opts.stm_flags in
+ let open Vernac.State in
+ let doc, sid =
+ Stm.(new_doc
+ { doc_type = Interactive opts.toplevel_name;
+ iload_path; require_libs; stm_options;
+ }) in
+ let state = { doc; sid; proof = None; time = opts.time } in
+ Ccompile.load_init_vernaculars opts ~state, opts
+
+(* To remove in 8.11 *)
+let call_coqc args =
+ let remove str arr = Array.(of_list List.(filter (fun l -> not String.(equal l str)) (to_list arr))) in
+ let coqc_name = Filename.remove_extension (System.get_toplevel_path "coqc") in
+ let args = remove "-compile" args in
+ Unix.execv coqc_name args
+
+let deprecated_coqc_warning = CWarnings.(create
+ ~name:"deprecate-compile-arg"
+ ~category:"toplevel"
+ ~default:Enabled
+ (fun opt_name -> Pp.(seq [str "The option "; str opt_name; str" is deprecated, please use coqc."])))
+
+let rec coqc_deprecated_check args acc extras =
+ match extras with
+ | [] -> acc
+ | "-o" :: _ :: rem ->
+ deprecated_coqc_warning "-o";
+ coqc_deprecated_check args acc rem
+ | ("-compile"|"-compile-verbose") :: file :: rem ->
+ deprecated_coqc_warning "-compile";
+ call_coqc args
+ | x :: rem ->
+ coqc_deprecated_check args (x::acc) rem
+
let coqtop_init ~opts extra =
init_color opts;
CoqworkmgrApi.(init !async_proofs_worker_priority);
@@ -266,20 +259,28 @@ let coqtop_init ~opts extra =
let coqtop_toplevel =
{ init = coqtop_init
; run = Coqloop.loop
- ; opts = Coqargs.default_opts
+ ; opts = Coqargs.default
}
let start_coq custom =
- match init_toplevel custom.opts custom.init (List.tl (Array.to_list Sys.argv)) with
- (* Batch mode *)
- | Some state, opts when not opts.batch_mode ->
- custom.run ~opts ~state;
- exit 1
- | _ , opts ->
- flush_all();
- if opts.output_context then begin
- let sigma, env = Pfedit.get_current_context () in
- Feedback.msg_notice (Flags.(with_option raw_print (Prettyp.print_full_pure_context env) sigma) ++ fnl ())
- end;
- CProfile.print_profile ();
- exit 0
+ let init_feeder = Feedback.add_feeder Coqloop.coqloop_feed in
+ (* Init phase *)
+ let state, opts =
+ try
+ let opts, extras =
+ init_toplevel
+ ~help:Usage.print_usage_coqtop ~init:default custom.init
+ (List.tl (Array.to_list Sys.argv)) in
+ let extras = coqc_deprecated_check Sys.argv [] extras in
+ if not (CList.is_empty extras) then begin
+ prerr_endline ("Don't know what to do with "^String.concat " " extras);
+ prerr_endline "See -help for the list of supported options";
+ exit 1
+ end;
+ init_toploop opts
+ with any ->
+ flush_all();
+ fatal_error_exn any in
+ Feedback.del_feeder init_feeder;
+ if not opts.batch then custom.run ~opts ~state;
+ exit 0
diff --git a/toplevel/coqtop.mli b/toplevel/coqtop.mli
index c95d0aca55..300a7a039b 100644
--- a/toplevel/coqtop.mli
+++ b/toplevel/coqtop.mli
@@ -12,14 +12,24 @@
[init] is used to do custom command line argument parsing.
[run] launches a custom toplevel.
*)
-open Coqargs
+
+type init_fn = opts:Coqargs.t -> string list -> Coqargs.t * string list
type custom_toplevel =
- { init : opts:coq_cmdopts -> string list -> coq_cmdopts * string list
- ; run : opts:coq_cmdopts -> state:Vernac.State.t -> unit
- ; opts : Coqargs.coq_cmdopts
+ { init : init_fn
+ ; run : opts:Coqargs.t -> state:Vernac.State.t -> unit
+ ; opts : Coqargs.t
}
+(** [init_toplevel ~help ~init custom_init arg_list]
+ Common Coq initialization and argument parsing *)
+val init_toplevel
+ : help:(unit -> unit)
+ -> init:Coqargs.t
+ -> init_fn
+ -> string list
+ -> Coqargs.t * string list
+
val coqtop_toplevel : custom_toplevel
(** The Coq main module. [start custom] will parse the command line,
diff --git a/toplevel/g_toplevel.mlg b/toplevel/g_toplevel.mlg
index 5aba3d6b0b..7f1cca277e 100644
--- a/toplevel/g_toplevel.mlg
+++ b/toplevel/g_toplevel.mlg
@@ -21,7 +21,7 @@ type vernac_toplevel =
| VernacControl of vernac_control
module Toplevel_ : sig
- val vernac_toplevel : vernac_toplevel CAst.t Entry.t
+ val vernac_toplevel : vernac_toplevel CAst.t option Entry.t
end = struct
let gec_vernac s = Entry.create ("toplevel:" ^ s)
let vernac_toplevel = gec_vernac "vernac_toplevel"
@@ -34,14 +34,14 @@ open Toplevel_
GRAMMAR EXTEND Gram
GLOBAL: vernac_toplevel;
vernac_toplevel: FIRST
- [ [ IDENT "Drop"; "." -> { CAst.make VernacDrop }
- | IDENT "Quit"; "." -> { CAst.make VernacQuit }
+ [ [ IDENT "Drop"; "." -> { Some (CAst.make VernacDrop) }
+ | IDENT "Quit"; "." -> { Some (CAst.make VernacQuit) }
| IDENT "Backtrack"; n = natural ; m = natural ; p = natural; "." ->
- { CAst.make (VernacBacktrack (n,m,p)) }
- | cmd = Pvernac.main_entry ->
+ { Some (CAst.make (VernacBacktrack (n,m,p))) }
+ | cmd = Pvernac.Vernac_.main_entry ->
{ match cmd with
- | None -> raise Stm.End_of_input
- | Some (loc,c) -> CAst.make ~loc (VernacControl c) }
+ | None -> None
+ | Some (loc,c) -> Some (CAst.make ~loc (VernacControl c)) }
]
]
;
@@ -49,6 +49,8 @@ END
{
-let parse_toplevel pa = Pcoq.Entry.parse vernac_toplevel pa
+let vernac_toplevel pm =
+ Pvernac.Unsafe.set_tactic_entry pm;
+ vernac_toplevel
}
diff --git a/toplevel/toplevel.mllib b/toplevel/toplevel.mllib
index 732744eb42..ddd11fd160 100644
--- a/toplevel/toplevel.mllib
+++ b/toplevel/toplevel.mllib
@@ -2,8 +2,10 @@ Vernac
Usage
Coqinit
Coqargs
+Coqcargs
G_toplevel
Coqloop
Ccompile
Coqtop
WorkerLoop
+Coqc
diff --git a/toplevel/usage.ml b/toplevel/usage.ml
index c43538017c..277f8b7367 100644
--- a/toplevel/usage.ml
+++ b/toplevel/usage.ml
@@ -23,7 +23,7 @@ let machine_readable_version ret =
let extra_usage = ref []
let add_to_usage name text = extra_usage := (name,text) :: !extra_usage
-let print_usage_channel co command =
+let print_usage_common co command =
output_string co command;
output_string co "Coq options are:\n";
output_string co
@@ -48,14 +48,6 @@ let print_usage_channel co command =
\n -lv f (idem)\
\n -load-vernac-object f load Coq object file f.vo\
\n -require path load Coq library path and import it (Require Import path.)\
-\n -compile f.v compile Coq file f.v (implies -batch)\
-\n -compile-verbose f.v verbosely compile Coq file f.v (implies -batch)\
-\n -o f.vo use f.vo as the output file name\
-\n -quick quickly compile .v files to .vio files (skip proofs)\
-\n -schedule-vio2vo j f1..fn run up to j instances of Coq to turn each fi.vio\
-\n into fi.vo\
-\n -schedule-vio-checking j f1..fn run up to j instances of Coq to check all\
-\n proofs in each fi.vio\
\n\
\n -where print Coq's standard library location and exit\
\n -config, --config print Coq's configuration information and exit\
@@ -66,16 +58,15 @@ let print_usage_channel co command =
\n -quiet unset display of extra information (implies -w \"-all\")\
\n -w (w1,..,wn) configure display of warnings\
\n -color (yes|no|auto) configure color output\
+\n -emacs tells Coq it is executed under Emacs\
\n\
\n -q skip loading of rcfile\
\n -init-file f set the rcfile to f\
-\n -batch batch mode (exits just after arguments parsing)\
-\n -boot boot mode (implies -q and -batch)\
+\n -boot boot mode (allows to overload the `Coq` library prefix)\
\n -bt print backtraces (requires configure debug flag)\
\n -debug debug mode (implies -bt)\
\n -diffs (on|off|removed) highlight differences between proof steps\
\n -stm-debug STM debug mode (will trace every transaction)\
-\n -emacs tells Coq it is executed under Emacs\
\n -noglob do not dump globalizations\
\n -dump-glob f dump globalizations in file f (to be used by coqdoc)\
\n -impredicative-set set sort Set impredicative\
@@ -88,8 +79,8 @@ let print_usage_channel co command =
\n (use environment variable\
\n OCAML_GC_STATS=\"/tmp/gclog.txt\"\
\n for full Gc stats dump)\
-\n -bytecode-compiler (yes|no) controls the vm_compute machinery\
-\n -native-compiler (yes|no|ondemand) controls the native_compute machinery\
+\n -bytecode-compiler (yes|no) enable the vm_compute reduction machine\
+\n -native-compiler (yes|no|ondemand) enable the native_compute reduction machine\
\n -h, -help, --help print this list of options\
\n";
List.iter (fun (name, text) ->
@@ -101,21 +92,46 @@ let print_usage_channel co command =
(* print the usage on standard error *)
-let print_usage = print_usage_channel stderr
-
let print_usage_coqtop () =
- print_usage "Usage: coqtop <options>\n\n";
+ print_usage_common stderr "Usage: coqtop <options>\n\n";
+ output_string stderr "\n\
+coqtop specific options:\
+\n\
+\n -batch batch mode (exits just after argument parsing)\
+\n\
+\nDeprecated options [use coqc instead]:\
+\n\
+\n -compile f.v compile Coq file f.v (implies -batch)\
+\n -compile-verbose f.v verbosely compile Coq file f.v (implies -batch)\
+\n -o f.vo use f.vo as the output file name\
+\n";
flush stderr ;
exit 1
let print_usage_coqc () =
- print_usage "Usage: coqc <options> <Coq options> file...\n\
-\noptions are:\
-\n -verbose compile verbosely\
-\n -image f specify an alternative executable for Coq\
-\n -opt run the native-code version of Coq\
-\n -byte run the bytecode version of Coq\
-\n -t keep temporary files\n\n";
+ print_usage_common stderr "Usage: coqc <options> <Coq options> file...";
+ output_string stderr "\n\
+coqc specific options:\
+\n\
+\n -o f.vo use f.vo as the output file name\
+\n -verbose compile and output the input file\
+\n -quick quickly compile .v files to .vio files (skip proofs)\
+\n -schedule-vio2vo j f1..fn run up to j instances of Coq to turn each fi.vio\
+\n into fi.vo\
+\n -schedule-vio-checking j f1..fn run up to j instances of Coq to check all\
+\n proofs in each fi.vio\
+\n\
+\nUndocumented:\
+\n -vio2vo [see manual]\
+\n -check-vio-tasks [see manual]\
+\n\
+\nDeprecated options:\
+\n\
+\n -image f specify an alternative executable for Coq\
+\n -opt run the native-code version of Coq\
+\n -byte run the bytecode version of Coq\
+\n -t keep temporary files\
+\n -outputstate file save summary state in file \
+\n";
flush stderr ;
exit 1
-
diff --git a/toplevel/usage.mli b/toplevel/usage.mli
index fbb0117d45..64170adaa4 100644
--- a/toplevel/usage.mli
+++ b/toplevel/usage.mli
@@ -13,9 +13,6 @@
val version : int -> 'a
val machine_readable_version : int -> 'a
-(** {6 Prints the usage on the error output, preceeded by a user-provided message. } *)
-val print_usage : string -> unit
-
(** {6 Enable toploop plugins to insert some text in the usage message. } *)
val add_to_usage : string -> string -> unit
diff --git a/toplevel/vernac.ml b/toplevel/vernac.ml
index d8465aac27..45ca658857 100644
--- a/toplevel/vernac.ml
+++ b/toplevel/vernac.ml
@@ -68,10 +68,8 @@ let interp_vernac ~check ~interactive ~state ({CAst.loc;_} as com) =
if ntip <> `NewTip then
anomaly (str "vernac.ml: We got an unfocus operation on the toplevel!");
- (* Due to bug #5363 we cannot use observe here as we should,
- it otherwise reveals bugs *)
- (* Stm.observe nsid; *)
- let ndoc = if check then Stm.finish ~doc else doc in
+ (* Force the command *)
+ let ndoc = if check then Stm.observe ~doc nsid else doc in
let new_proof = Proof_global.give_me_the_proof_opt () in
{ state with doc = ndoc; sid = nsid; proof = new_proof; }
with reraise ->
@@ -92,51 +90,37 @@ let load_vernac_core ~echo ~check ~interactive ~state file =
let in_echo = if echo then Some (open_utf8_file_in file) else None in
let input_cleanup () = close_in in_chan; Option.iter close_in in_echo in
- let in_pa = Pcoq.Parsable.make ~file:(Loc.InFile file) (Stream.of_channel in_chan) in
- let rstate = ref state in
- (* For beautify, list of parsed sids *)
- let rids = ref [] in
+ let in_pa =
+ Pcoq.Parsable.make ~file:(Loc.InFile file) (Stream.of_channel in_chan) in
let open State in
- try
- (* we go out of the following infinite loop when a End_of_input is
- * raised, which means that we raised the end of the file being loaded *)
- while true do
- let { CAst.loc; _ } as ast =
- Stm.parse_sentence ~doc:!rstate.doc !rstate.sid in_pa
- (* If an error in parsing occurs, we propagate the exception
- so the caller of load_vernac will take care of it. However,
- in the future it could be possible that we want to handle
- all the errors as feedback events, thus in this case we
- should relay the exception here for convenience. A
- possibility is shown below, however we may want to refactor
- this code:
-
- try Stm.parse_sentence !rsid in_pa
- with
- | any when not is_end_of_input any ->
- let (e, info) = CErrors.push any in
- let loc = Loc.get_loc info in
- let msg = CErrors.iprint (e, info) in
- Feedback.msg_error ?loc msg;
- iraise (e, info)
- *)
- in
- (* Printing of vernacs *)
- Option.iter (vernac_echo ?loc) in_echo;
-
- checknav_simple ast;
- let state = Flags.silently (interp_vernac ~check ~interactive ~state:!rstate) ast in
- rids := state.sid :: !rids;
- rstate := state;
- done;
- input_cleanup ();
- !rstate, !rids, Pcoq.Parsable.comment_state in_pa
+
+ (* ids = For beautify, list of parsed sids *)
+ let rec loop state ids =
+ match
+ Stm.parse_sentence
+ ~doc:state.doc ~entry:Pvernac.main_entry state.sid in_pa
+ with
+ | None ->
+ input_cleanup ();
+ state, ids, Pcoq.Parsable.comment_state in_pa
+ | Some (loc, ast) ->
+ let ast = CAst.make ~loc ast in
+
+ (* Printing of AST for -compile-verbose *)
+ Option.iter (vernac_echo ~loc) in_echo;
+
+ checknav_simple ast;
+
+ let state =
+ Flags.silently (interp_vernac ~check ~interactive ~state) ast in
+
+ loop state (state.sid :: ids)
+ in
+ try loop state []
with any -> (* whatever the exception *)
let (e, info) = CErrors.push any in
input_cleanup ();
- match e with
- | Stm.End_of_input -> !rstate, !rids, Pcoq.Parsable.comment_state in_pa
- | reraise -> iraise (e, info)
+ iraise (e, info)
let process_expr ~state loc_ast =
checknav_deep loc_ast;
diff --git a/toplevel/workerLoop.ml b/toplevel/workerLoop.ml
index e4e9a87365..f922ad8fee 100644
--- a/toplevel/workerLoop.ml
+++ b/toplevel/workerLoop.ml
@@ -23,7 +23,7 @@ let arg_init init ~opts extra_args =
let start ~init ~loop =
let open Coqtop in
let custom = {
- opts = Coqargs.default_opts;
+ opts = Coqargs.default;
init = arg_init init;
run = (fun ~opts:_ ~state:_ -> loop ());
} in
diff --git a/vernac/auto_ind_decl.ml b/vernac/auto_ind_decl.ml
index d9787bc73c..868a6ed3e9 100644
--- a/vernac/auto_ind_decl.ml
+++ b/vernac/auto_ind_decl.ml
@@ -245,6 +245,7 @@ let build_beq_scheme mode kn =
| Fix _ -> raise (EqUnknown "fix")
| Meta _ -> raise (EqUnknown "meta-variable")
| Evar _ -> raise (EqUnknown "existential variable")
+ | Int _ -> raise (EqUnknown "int")
in
aux t
in
diff --git a/vernac/classes.ml b/vernac/classes.ml
index 748a2628c5..dd49f09d35 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -269,9 +269,9 @@ let do_instance env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode ct
Pretyping.check_evars env (Evd.from_env env) sigma termtype;
let termtype = to_constr sigma termtype in
let term = Option.map (to_constr ~abort_on_undefined_evars:false sigma) term in
- if not (Evd.has_undefined sigma) && not (Option.is_empty term) then
+ if not (Evd.has_undefined sigma) && not (Option.is_empty props) then
declare_instance_constant k pri global imps ?hook id decl poly sigma (Option.get term) termtype
- else if program_mode || refine || Option.is_empty term then
+ else if program_mode || refine || Option.is_empty props then
declare_instance_open env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl (List.map RelDecl.get_name ctx) term termtype
else CErrors.user_err Pp.(str "Unsolved obligations remaining.");
id
@@ -376,9 +376,11 @@ let context poly l =
| [] -> assert false
| [_] -> Evd.const_univ_entry ~poly sigma
| _::_::_ ->
- (* TODO: explain this little belly dance *)
if Lib.sections_are_opened ()
then
+ (* More than 1 variable in a section: we can't associate
+ universes to any specific variable so we declare them
+ separately. *)
begin
let uctx = Evd.universe_context_set sigma in
Declare.declare_universe_context poly uctx;
@@ -386,8 +388,11 @@ let context poly l =
else Monomorphic_const_entry Univ.ContextSet.empty
end
else if poly then
+ (* Multiple polymorphic axioms: they are all polymorphic the same way. *)
Evd.const_univ_entry ~poly sigma
else
+ (* Multiple monomorphic axioms: declare universes separately
+ to avoid redeclaring them. *)
begin
let uctx = Evd.universe_context_set sigma in
Declare.declare_universe_context poly uctx;
diff --git a/vernac/comAssumption.ml b/vernac/comAssumption.ml
index 4b8371f5c3..7301e1fff7 100644
--- a/vernac/comAssumption.ml
+++ b/vernac/comAssumption.ml
@@ -178,3 +178,29 @@ let do_assumptions kind nl l =
in
subst'@subst, status' && status, next_uctx uctx)
([], true, uctx) l)
+
+let do_primitive id prim typopt =
+ if Lib.sections_are_opened () then
+ CErrors.user_err Pp.(str "Declaring a primitive is not allowed in sections.");
+ if Dumpglob.dump () then Dumpglob.dump_definition id false "ax";
+ let env = Global.env () in
+ let evd = Evd.from_env env in
+ let evd, typopt = Option.fold_left_map
+ (interp_type_evars_impls ~impls:empty_internalization_env env)
+ evd typopt
+ in
+ let evd = Evd.minimize_universes evd in
+ let uvars, impls, typopt = match typopt with
+ | None -> Univ.LSet.empty, [], None
+ | Some (ty,impls) ->
+ EConstr.universes_of_constr evd ty, impls, Some (EConstr.to_constr evd ty)
+ in
+ let evd = Evd.restrict_universe_context evd uvars in
+ let uctx = UState.check_mono_univ_decl (Evd.evar_universe_context evd) UState.default_univ_decl in
+ let entry = { prim_entry_type = typopt;
+ prim_entry_univs = uctx;
+ prim_entry_content = prim;
+ }
+ in
+ let _kn = declare_constant id.CAst.v (PrimitiveEntry entry,IsPrimitive) in
+ register_message id.CAst.v
diff --git a/vernac/comAssumption.mli b/vernac/comAssumption.mli
index 56932360a9..c5bf3725a9 100644
--- a/vernac/comAssumption.mli
+++ b/vernac/comAssumption.mli
@@ -33,3 +33,5 @@ val declare_assumption : coercion_flag -> assumption_kind ->
UnivNames.universe_binders -> Impargs.manual_implicits ->
bool (** implicit *) -> Declaremods.inline -> variable CAst.t ->
GlobRef.t * Univ.Instance.t * bool
+
+val do_primitive : lident -> CPrimitives.op_or_type -> constr_expr option -> unit
diff --git a/vernac/comInductive.ml b/vernac/comInductive.ml
index 92b1ff7572..afee2a5868 100644
--- a/vernac/comInductive.ml
+++ b/vernac/comInductive.ml
@@ -83,10 +83,9 @@ type structured_one_inductive_expr = {
type structured_inductive_expr =
local_binder_expr list * structured_one_inductive_expr list
-let minductive_message warn = function
+let minductive_message = function
| [] -> user_err Pp.(str "No inductive definition.")
- | [x] -> (Id.print x ++ str " is defined" ++
- if warn then str " as a non-primitive record" else mt())
+ | [x] -> (Id.print x ++ str " is defined")
| l -> hov 0 (prlist_with_sep pr_comma Id.print l ++
spc () ++ str "are defined")
@@ -531,6 +530,12 @@ let is_recursive mie =
List.exists (fun t -> is_recursive_constructor (nparams+1) t) ind.mind_entry_lc
| _ -> false
+let warn_non_primitive_record =
+ CWarnings.create ~name:"non-primitive-record" ~category:"record"
+ (fun indsp ->
+ (hov 0 (str "The record " ++ Nametab.pr_global_env Id.Set.empty (IndRef indsp) ++
+ strbrk" could not be defined as a primitive record")))
+
let declare_mutual_inductive_with_eliminations mie pl impls =
(* spiwack: raises an error if the structure is supposed to be non-recursive,
but isn't *)
@@ -545,6 +550,8 @@ let declare_mutual_inductive_with_eliminations mie pl impls =
let names = List.map (fun e -> e.mind_entry_typename) mie.mind_entry_inds in
let (_, kn), prim = declare_mind mie in
let mind = Global.mind_of_delta_kn kn in
+ if match mie.mind_entry_record with Some (Some _) -> not prim | _ -> false
+ then warn_non_primitive_record (mind,0);
Declare.declare_univ_binders (IndRef (mind,0)) pl;
List.iteri (fun i (indimpls, constrimpls) ->
let ind = (mind,i) in
@@ -556,8 +563,7 @@ let declare_mutual_inductive_with_eliminations mie pl impls =
(ConstructRef (ind, succ j)) impls)
constrimpls)
impls;
- let warn_prim = match mie.mind_entry_record with Some (Some _) -> not prim | _ -> false in
- Flags.if_verbose Feedback.msg_info (minductive_message warn_prim names);
+ Flags.if_verbose Feedback.msg_info (minductive_message names);
if mie.mind_entry_private == None
then declare_default_schemes mind;
mind
diff --git a/vernac/g_vernac.mlg b/vernac/g_vernac.mlg
index 3bc4aecdb1..0664e18130 100644
--- a/vernac/g_vernac.mlg
+++ b/vernac/g_vernac.mlg
@@ -61,7 +61,8 @@ let make_bullet s =
| _ -> assert false
let parse_compat_version = let open Flags in function
- | "8.9" -> Current
+ | "8.10" -> Current
+ | "8.9" -> V8_9
| "8.8" -> V8_8
| "8.7" -> V8_7
| ("8.6" | "8.5" | "8.4" | "8.3" | "8.2" | "8.1" | "8.0") as s ->
@@ -218,12 +219,51 @@ GRAMMAR EXTEND Gram
{ VernacRegister(g, RegisterCoqlib quid) }
| IDENT "Register"; IDENT "Inline"; g = global ->
{ VernacRegister(g, RegisterInline) }
+ | IDENT "Primitive"; id = identref; typopt = OPT [ ":"; typ = lconstr -> { typ } ]; ":="; r = register_token ->
+ { VernacPrimitive(id, r, typopt) }
| IDENT "Universe"; l = LIST1 identref -> { VernacUniverse l }
| IDENT "Universes"; l = LIST1 identref -> { VernacUniverse l }
| IDENT "Constraint"; l = LIST1 univ_constraint SEP "," -> { VernacConstraint l }
] ]
;
+ register_token:
+ [ [ r = register_prim_token -> { CPrimitives.OT_op r }
+ | r = register_type_token -> { CPrimitives.OT_type r } ] ]
+ ;
+
+ register_type_token:
+ [ [ "#int63_type" -> { CPrimitives.PT_int63 } ] ]
+ ;
+
+ register_prim_token:
+ [ [ "#int63_head0" -> { CPrimitives.Int63head0 }
+ | "#int63_tail0" -> { CPrimitives.Int63tail0 }
+ | "#int63_add" -> { CPrimitives.Int63add }
+ | "#int63_sub" -> { CPrimitives.Int63sub }
+ | "#int63_mul" -> { CPrimitives.Int63mul }
+ | "#int63_div" -> { CPrimitives.Int63div }
+ | "#int63_mod" -> { CPrimitives.Int63mod }
+ | "#int63_lsr" -> { CPrimitives.Int63lsr }
+ | "#int63_lsl" -> { CPrimitives.Int63lsl }
+ | "#int63_land" -> { CPrimitives.Int63land }
+ | "#int63_lor" -> { CPrimitives.Int63lor }
+ | "#int63_lxor" -> { CPrimitives.Int63lxor }
+ | "#int63_addc" -> { CPrimitives.Int63addc }
+ | "#int63_subc" -> { CPrimitives.Int63subc }
+ | "#int63_addcarryc" -> { CPrimitives.Int63addCarryC }
+ | "#int63_subcarryc" -> { CPrimitives.Int63subCarryC }
+ | "#int63_mulc" -> { CPrimitives.Int63mulc }
+ | "#int63_diveucl" -> { CPrimitives.Int63diveucl }
+ | "#int63_div21" -> { CPrimitives.Int63div21 }
+ | "#int63_addmuldiv" -> { CPrimitives.Int63addMulDiv }
+ | "#int63_eq" -> { CPrimitives.Int63eq }
+ | "#int63_lt" -> { CPrimitives.Int63lt }
+ | "#int63_le" -> { CPrimitives.Int63le }
+ | "#int63_compare" -> { CPrimitives.Int63compare }
+ ] ]
+ ;
+
thm_token:
[ [ "Theorem" -> { Theorem }
| IDENT "Lemma" -> { Lemma }
diff --git a/vernac/himsg.ml b/vernac/himsg.ml
index ebbec86b9c..f78b43e2fa 100644
--- a/vernac/himsg.ml
+++ b/vernac/himsg.ml
@@ -598,6 +598,20 @@ let explain_var_not_found env id =
spc () ++ str "was not found" ++
spc () ++ str "in the current" ++ spc () ++ str "environment" ++ str "."
+
+let explain_evar_not_found env sigma id =
+ let undef = Evar.Map.domain (Evd.undefined_map sigma) in
+ let all_undef_evars = Evar.Set.elements undef in
+ let f ev = Id.equal id (Termops.evar_suggested_name ev sigma) in
+ if List.exists f all_undef_evars then
+ (* The name is used for printing but is not user-given *)
+ str "?" ++ Id.print id ++
+ strbrk " is a generated name. Only user-given names for existential variables" ++
+ strbrk " can be referenced. To give a user name to an existential variable," ++
+ strbrk " introduce it with the ?[name] syntax."
+ else
+ str "Unknown existential variable."
+
let explain_wrong_case_info env (ind,u) ci =
let pi = pr_inductive env ind in
if eq_ind ci.ci_ind ind then
@@ -812,6 +826,7 @@ let explain_pretype_error env sigma err =
| UnifOccurCheck (ev,rhs) -> explain_occur_check env sigma ev rhs
| UnsolvableImplicit (evk,exp) -> explain_unsolvable_implicit env sigma evk exp
| VarNotFound id -> explain_var_not_found env id
+ | EvarNotFound id -> explain_evar_not_found env sigma id
| UnexpectedType (actual,expect) ->
let env, actual, expect = contract2 env sigma actual expect in
explain_unexpected_type env sigma actual expect
@@ -833,6 +848,7 @@ let explain_pretype_error env sigma err =
| TypingError t -> explain_type_error env sigma t
| CannotUnifyOccurrences (b,c1,c2,e) -> explain_cannot_unify_occurrences env sigma b c1 c2 e
| UnsatisfiableConstraints (c,comp) -> explain_unsatisfiable_constraints env sigma c comp
+
(* Module errors *)
open Modops
diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml
index 8f155adb8a..0dfbba0e83 100644
--- a/vernac/lemmas.ml
+++ b/vernac/lemmas.ml
@@ -340,7 +340,7 @@ let start_proof id ?pl kind sigma ?terminator ?sign ?(compute_guard=[]) ?hook c
| None -> standard_proof_terminator ?hook compute_guard
| Some terminator -> terminator ?hook compute_guard
in
- let sign =
+ let sign =
match sign with
| Some sign -> sign
| None -> initialize_named_context_for_proof ()
diff --git a/vernac/obligations.ml b/vernac/obligations.ml
index 6642d04c98..b4dd7d06b5 100644
--- a/vernac/obligations.ml
+++ b/vernac/obligations.ml
@@ -921,15 +921,15 @@ let obligation_hook prg obl num auto ctx' _ gr =
| (true, Evar_kinds.Define true) ->
if not transparent then err_not_transp ()
| _ -> ()
-in
+ in
let ctx' = match ctx' with None -> prg.prg_ctx | Some ctx' -> ctx' in
let inst, ctx' =
if not (pi2 prg.prg_kind) (* Not polymorphic *) then
(* The universe context was declared globally, we continue
from the new global environment. *)
- let evd = Evd.from_env (Global.env ()) in
- let ctx' = Evd.merge_universe_subst evd (Evd.universe_subst (Evd.from_ctx ctx')) in
- Univ.Instance.empty, Evd.evar_universe_context ctx'
+ let ctx = UState.make (Global.universes ()) in
+ let ctx' = UState.merge_subst ctx (UState.subst ctx') in
+ Univ.Instance.empty, ctx'
else
(* We get the right order somehow, but surely it could be enforced in a clearer way. *)
let uctx = UState.context ctx' in
diff --git a/vernac/ppvernac.ml b/vernac/ppvernac.ml
index 5eeeaada2d..d22e52e960 100644
--- a/vernac/ppvernac.ml
+++ b/vernac/ppvernac.ml
@@ -1182,6 +1182,12 @@ open Pputils
hov 2
(keyword "Register Inline" ++ spc() ++ pr_qualid qid)
)
+ | VernacPrimitive(id,r,typopt) ->
+ hov 2
+ (keyword "Primitive" ++ spc() ++ pr_lident id ++
+ (Option.cata (fun ty -> spc() ++ str":" ++ pr_spc_lconstr ty) (mt()) typopt) ++ spc() ++
+ str ":=" ++ spc() ++
+ str (CPrimitives.op_or_type_to_string r))
| VernacComments l ->
return (
hov 2
diff --git a/vernac/pvernac.ml b/vernac/pvernac.ml
index a647b2ef73..0e46df2320 100644
--- a/vernac/pvernac.ml
+++ b/vernac/pvernac.ml
@@ -12,6 +12,27 @@ open Pcoq
let uvernac = create_universe "vernac"
+type proof_mode = string
+
+(* Tactic parsing modes *)
+let register_proof_mode, find_proof_mode, lookup_proof_mode =
+ let proof_mode : (string, Vernacexpr.vernac_expr Entry.t) Hashtbl.t =
+ Hashtbl.create 19 in
+ let register_proof_mode ename e = Hashtbl.add proof_mode ename e; ename in
+ let find_proof_mode ename =
+ try Hashtbl.find proof_mode ename
+ with Not_found ->
+ CErrors.anomaly Pp.(str "proof mode not found: " ++ str ename) in
+ let lookup_proof_mode name =
+ if Hashtbl.mem proof_mode name then Some name
+ else None
+ in
+ register_proof_mode, find_proof_mode, lookup_proof_mode
+
+let proof_mode_to_string name = name
+
+let command_entry_ref = ref None
+
module Vernac_ =
struct
let gec_vernac s = Entry.create ("vernac:" ^ s)
@@ -39,17 +60,24 @@ module Vernac_ =
] in
Pcoq.grammar_extend main_entry None (None, [None, None, rule])
- let command_entry_ref = ref noedit_mode
+ let select_tactic_entry spec =
+ match spec with
+ | None -> noedit_mode
+ | Some ename -> find_proof_mode ename
+
let command_entry =
Pcoq.Entry.of_parser "command_entry"
- (fun strm -> Pcoq.Entry.parse_token_stream !command_entry_ref strm)
+ (fun strm -> Pcoq.Entry.parse_token_stream (select_tactic_entry !command_entry_ref) strm)
end
-let main_entry = Vernac_.main_entry
+module Unsafe = struct
+ let set_tactic_entry oname = command_entry_ref := oname
+end
-let set_command_entry e = Vernac_.command_entry_ref := e
-let get_command_entry () = !Vernac_.command_entry_ref
+let main_entry proof_mode =
+ Unsafe.set_tactic_entry proof_mode;
+ Vernac_.main_entry
let () =
register_grammar Genredexpr.wit_red_expr (Vernac_.red_expr);
diff --git a/vernac/pvernac.mli b/vernac/pvernac.mli
index b2f8f71462..fa251281dc 100644
--- a/vernac/pvernac.mli
+++ b/vernac/pvernac.mli
@@ -14,6 +14,8 @@ open Vernacexpr
val uvernac : gram_universe
+type proof_mode
+
module Vernac_ :
sig
val gallina : vernac_expr Entry.t
@@ -24,13 +26,31 @@ module Vernac_ :
val rec_definition : (fixpoint_expr * decl_notation list) Entry.t
val noedit_mode : vernac_expr Entry.t
val command_entry : vernac_expr Entry.t
+ val main_entry : (Loc.t * vernac_control) option Entry.t
val red_expr : raw_red_expr Entry.t
val hint_info : Hints.hint_info_expr Entry.t
end
+(* To be removed when the parser is made functional wrt the tactic
+ * non terminal *)
+module Unsafe : sig
+ (* To let third party grammar entries reuse Vernac_ and
+ * do something with the proof mode *)
+ val set_tactic_entry : proof_mode option -> unit
+end
+
(** The main entry: reads an optional vernac command *)
-val main_entry : (Loc.t * vernac_control) option Entry.t
+val main_entry : proof_mode option -> (Loc.t * vernac_control) option Entry.t
+
+(** Grammar entry for tactics: proof mode(s).
+ By default Coq's grammar has an empty entry (non-terminal) for
+ tactics. A plugin can register its non-terminal by providing a name
+ and a grammar entry.
+
+ For example the Ltac plugin register the "Classic" grammar
+ entry for parsing its tactics.
+ *)
-(** Handling of the proof mode entry *)
-val get_command_entry : unit -> vernac_expr Entry.t
-val set_command_entry : vernac_expr Entry.t -> unit
+val register_proof_mode : string -> Vernacexpr.vernac_expr Entry.t -> proof_mode
+val lookup_proof_mode : string -> proof_mode option
+val proof_mode_to_string : proof_mode -> string
diff --git a/vernac/record.ml b/vernac/record.ml
index 2867ad1437..ed5edb7e3b 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -176,19 +176,20 @@ let typecheck_params_and_fields finite def poly pl ps records =
else sigma, typ
in
let (sigma, typs) = List.fold_left2_map fold sigma typs data in
- let sigma = Evd.minimize_universes sigma in
- let newps = List.map (EConstr.to_rel_decl sigma) newps in
+ let sigma, (newps, ans) = Evarutil.finalize sigma (fun nf ->
+ let newps = List.map (RelDecl.map_constr_het nf) newps in
+ let map (impls, newfs) typ =
+ let newfs = List.map (RelDecl.map_constr_het nf) newfs in
+ let typ = nf typ in
+ (typ, impls, newfs)
+ in
+ let ans = List.map2 map data typs in
+ newps, ans)
+ in
let univs = Evd.check_univ_decl ~poly sigma decl in
let ubinders = Evd.universe_binders sigma in
let ce t = Pretyping.check_evars env0 (Evd.from_env env0) sigma (EConstr.of_constr t) in
let () = List.iter (iter_constr ce) (List.rev newps) in
- let map (impls, newfs) typ =
- let newfs = List.map (EConstr.to_rel_decl sigma) newfs in
- let typ = EConstr.to_constr sigma typ in
- List.iter (iter_constr ce) (List.rev newfs);
- (typ, impls, newfs)
- in
- let ans = List.map2 map data typs in
ubinders, univs, template, newps, imps, ans
type record_error =
@@ -270,12 +271,6 @@ let instantiate_possibly_recursive_type ind u ntypes paramdecls fields =
let subst' = List.init ntypes (fun i -> mkIndU ((ind, ntypes - i - 1), u)) in
Termops.substl_rel_context (subst @ subst') fields
-let warn_non_primitive_record =
- CWarnings.create ~name:"non-primitive-record" ~category:"record"
- (fun (env,indsp) ->
- (hov 0 (str "The record " ++ Printer.pr_inductive env indsp ++
- strbrk" could not be defined as a primitive record")))
-
(* We build projections *)
let declare_projections indsp ctx ?(kind=StructureComponent) binder_name coers fieldimpls fields =
let env = Global.env() in
@@ -293,16 +288,9 @@ let declare_projections indsp ctx ?(kind=StructureComponent) binder_name coers f
let fields = instantiate_possibly_recursive_type (fst indsp) u mib.mind_ntypes paramdecls fields in
let lifted_fields = Termops.lift_rel_context 1 fields in
let primitive =
- if !primitive_flag then
- let is_primitive =
- match mib.mind_record with
- | PrimRecord _ -> true
- | FakeRecord | NotRecord -> false
- in
- if not is_primitive then
- warn_non_primitive_record (env,indsp);
- is_primitive
- else false
+ match mib.mind_record with
+ | PrimRecord _ -> true
+ | FakeRecord | NotRecord -> false
in
let (_,_,kinds,sp_projs,_) =
List.fold_left3
@@ -426,9 +414,15 @@ let declare_structure finite ubinders univs paramimpls params template ?(kind=St
mind_entry_lc = [type_constructor] }
in
let blocks = List.mapi mk_block record_data in
+ let primitive =
+ !primitive_flag &&
+ List.for_all (fun (_,_,_,_,fields,_,_) -> List.exists is_local_assum fields) record_data
+ (* will warn_non_primitive_record in declare_projections if we try
+ to declare a 0-field record *)
+ in
let mie =
{ mind_entry_params = params;
- mind_entry_record = Some (if !primitive_flag then Some binder_name else None);
+ mind_entry_record = Some (if primitive then Some binder_name else None);
mind_entry_finite = finite;
mind_entry_inds = blocks;
mind_entry_private = None;
diff --git a/vernac/topfmt.ml b/vernac/topfmt.ml
index b4b893a3fd..ed93267665 100644
--- a/vernac/topfmt.ml
+++ b/vernac/topfmt.ml
@@ -335,6 +335,7 @@ type execution_phase =
| LoadingPrelude
| LoadingRcFile
| InteractiveLoop
+ | CompilationPhase
let default_phase = ref InteractiveLoop
@@ -373,7 +374,9 @@ let pr_phase ?loc () =
Some (str "While loading initial state:" ++ Option.cata (fun loc -> fnl () ++ pr_loc loc) (mt ()) loc)
| _, Some loc -> Some (pr_loc loc)
| ParsingCommandLine, _
- | Initialization, _ -> None
+ | Initialization, _
+ | CompilationPhase, _ ->
+ None
| InteractiveLoop, _ ->
(* Note: interactive messages such as "foo is defined" are not located *)
None
diff --git a/vernac/topfmt.mli b/vernac/topfmt.mli
index 5f84c5edee..b0e3b3772c 100644
--- a/vernac/topfmt.mli
+++ b/vernac/topfmt.mli
@@ -60,6 +60,7 @@ type execution_phase =
| LoadingPrelude
| LoadingRcFile
| InteractiveLoop
+ | CompilationPhase
val in_phase : phase:execution_phase -> ('a -> 'b) -> 'a -> 'b
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 26859cd2cf..7611355100 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -489,6 +489,28 @@ let vernac_notation ~module_local =
let vernac_custom_entry ~module_local s =
Metasyntax.declare_custom_entry module_local s
+(* Default proof mode, to be set at the beginning of proofs for
+ programs that cannot be statically classified. *)
+let default_proof_mode = ref (Pvernac.register_proof_mode "Noedit" Pvernac.Vernac_.noedit_mode)
+let get_default_proof_mode () = !default_proof_mode
+
+let get_default_proof_mode_opt () = Pvernac.proof_mode_to_string !default_proof_mode
+let set_default_proof_mode_opt name =
+ default_proof_mode :=
+ match Pvernac.lookup_proof_mode name with
+ | Some pm -> pm
+ | None -> CErrors.user_err Pp.(str (Format.sprintf "No proof mode named \"%s\"." name))
+
+let proof_mode_opt_name = ["Default";"Proof";"Mode"]
+let () =
+ Goptions.declare_string_option Goptions.{
+ optdepr = false;
+ optname = "default proof mode" ;
+ optkey = proof_mode_opt_name;
+ optread = get_default_proof_mode_opt;
+ optwrite = set_default_proof_mode_opt;
+ }
+
(***********)
(* Gallina *)
@@ -2010,21 +2032,31 @@ let vernac_locate = function
let vernac_register qid r =
let gr = Smartlocate.global_with_alias qid in
- if Proof_global.there_are_pending_proofs () then
+ if Proof_global.there_are_pending_proofs () then
user_err Pp.(str "Cannot register a primitive while in proof editing mode.");
match r with
| RegisterInline ->
- if not (isConstRef gr) then
- user_err Pp.(str "Register inline: a constant is expected");
- Global.register_inline (destConstRef gr)
+ begin match gr with
+ | ConstRef c -> Global.register_inline c
+ | _ -> CErrors.user_err (Pp.str "Register Inline: expecting a constant")
+ end
| RegisterCoqlib n ->
- let path, id = Libnames.repr_qualid n in
- if DirPath.equal path Retroknowledge.int31_path
- then
- let f = Retroknowledge.(KInt31 (int31_field_of_string (Id.to_string id))) in
- Global.register f gr
- else
- Coqlib.register_ref (Libnames.string_of_qualid n) gr
+ let ns, id = Libnames.repr_qualid n in
+ if DirPath.equal (dirpath_of_string "kernel") ns then begin
+ if Lib.sections_are_opened () then
+ user_err Pp.(str "Registering a kernel type is not allowed in sections");
+ let pind = match Id.to_string id with
+ | "ind_bool" -> CPrimitives.PIT_bool
+ | "ind_carry" -> CPrimitives.PIT_carry
+ | "ind_pair" -> CPrimitives.PIT_pair
+ | "ind_cmp" -> CPrimitives.PIT_cmp
+ | k -> CErrors.user_err Pp.(str "Register: unknown identifier “" ++ str k ++ str "” in the “kernel” namespace")
+ in
+ match gr with
+ | IndRef ind -> Global.register_inductive ind pind
+ | _ -> CErrors.user_err (Pp.str "Register in kernel: expecting an inductive type")
+ end
+ else Coqlib.register_ref (Libnames.string_of_qualid n) gr
(********************)
(* Proof management *)
@@ -2115,13 +2147,9 @@ exception End_of_input
let vernac_load interp fname =
if Proof_global.there_are_pending_proofs () then
CErrors.user_err Pp.(str "Load is not supported inside proofs.");
- let interp x =
- let proof_mode = Proof_global.get_default_proof_mode_name () [@ocaml.warning "-3"] in
- Proof_global.activate_proof_mode proof_mode [@ocaml.warning "-3"];
- interp x in
- let parse_sentence = Flags.with_option Flags.we_are_parsing
+ let parse_sentence proof_mode = Flags.with_option Flags.we_are_parsing
(fun po ->
- match Pcoq.Entry.parse Pvernac.main_entry po with
+ match Pcoq.Entry.parse (Pvernac.main_entry proof_mode) po with
| Some x -> x
| None -> raise End_of_input) in
let fname =
@@ -2132,7 +2160,15 @@ let vernac_load interp fname =
let in_chan = open_utf8_file_in longfname in
Pcoq.Parsable.make ~file:(Loc.InFile longfname) (Stream.of_channel in_chan) in
begin
- try while true do interp (snd (parse_sentence input)) done
+ try while true do
+ let proof_mode =
+ if Proof_global.there_are_pending_proofs () then
+ Some (get_default_proof_mode ())
+ else
+ None
+ in
+ interp (snd (parse_sentence proof_mode input));
+ done
with End_of_input -> ()
end;
(* If Load left a proof open, we fail too. *)
@@ -2290,6 +2326,7 @@ let interp ?proof ~atts ~st c =
| VernacLocate l -> unsupported_attributes atts;
Feedback.msg_notice @@ vernac_locate l
| VernacRegister (qid, r) -> unsupported_attributes atts; vernac_register qid r
+ | VernacPrimitive (id, prim, typopt) -> unsupported_attributes atts; ComAssumption.do_primitive id prim typopt
| VernacComments l -> unsupported_attributes atts;
Flags.if_verbose Feedback.msg_info (str "Comments ok\n")
@@ -2312,8 +2349,7 @@ let interp ?proof ~atts ~st c =
Aux_file.record_in_aux_at "VernacProof" (tacs^" "^usings);
Option.iter vernac_set_end_tac tac;
Option.iter vernac_set_used_variables using
- | VernacProofMode mn -> unsupported_attributes atts;
- Proof_global.set_proof_mode mn [@ocaml.warning "-3"]
+ | VernacProofMode mn -> unsupported_attributes atts; ()
(* Extensions *)
| VernacExtend (opn,args) ->
diff --git a/vernac/vernacentries.mli b/vernac/vernacentries.mli
index 8d8d7cfcf0..4fbd3849b0 100644
--- a/vernac/vernacentries.mli
+++ b/vernac/vernacentries.mli
@@ -10,6 +10,11 @@
val dump_global : Libnames.qualid Constrexpr.or_by_notation -> unit
+(** Default proof mode set by `start_proof` *)
+val get_default_proof_mode : unit -> Pvernac.proof_mode
+
+val proof_mode_opt_name : string list
+
(** Vernacular entries *)
val vernac_require :
Libnames.qualid option -> bool option -> Libnames.qualid list -> unit
diff --git a/vernac/vernacexpr.ml b/vernac/vernacexpr.ml
index 68a17e316e..2eb901890b 100644
--- a/vernac/vernacexpr.ml
+++ b/vernac/vernacexpr.ml
@@ -378,6 +378,7 @@ type nonrec vernac_expr =
| VernacSearch of searchable * Goal_select.t option * search_restriction
| VernacLocate of locatable
| VernacRegister of qualid * register_kind
+ | VernacPrimitive of lident * CPrimitives.op_or_type * constr_expr option
| VernacComments of comment list
(* Proof management *)
diff --git a/vernac/vernacextend.ml b/vernac/vernacextend.ml
index 05687afd8b..f5cf3401d0 100644
--- a/vernac/vernacextend.ml
+++ b/vernac/vernacextend.ml
@@ -29,15 +29,15 @@ type vernac_type =
parallel : [ `Yes of solving_tac * anon_abstracting_tac | `No ];
proof_block_detection : proof_block_name option
}
- (* To be removed *)
- | VtProofMode of string
(* Queries are commands assumed to be "pure", that is to say, they
don't modify the interpretation state. *)
| VtQuery
+ (* Commands that change the current proof mode *)
+ | VtProofMode of string
(* To be removed *)
| VtMeta
| VtUnknown
-and vernac_start = string * opacity_guarantee * Names.Id.t list
+and vernac_start = opacity_guarantee * Names.Id.t list
and vernac_sideff_type = Names.Id.t list
and opacity_guarantee =
| GuaranteesOpacity (** Only generates opaque terms at [Qed] *)
diff --git a/vernac/vernacextend.mli b/vernac/vernacextend.mli
index 0d43eb1ee8..118907c31b 100644
--- a/vernac/vernacextend.mli
+++ b/vernac/vernacextend.mli
@@ -45,15 +45,15 @@ type vernac_type =
parallel : [ `Yes of solving_tac * anon_abstracting_tac | `No ];
proof_block_detection : proof_block_name option
}
- (* To be removed *)
- | VtProofMode of string
(* Queries are commands assumed to be "pure", that is to say, they
don't modify the interpretation state. *)
| VtQuery
+ (* Commands that change the current proof mode *)
+ | VtProofMode of string
(* To be removed *)
| VtMeta
| VtUnknown
-and vernac_start = string * opacity_guarantee * Names.Id.t list
+and vernac_start = opacity_guarantee * Names.Id.t list
and vernac_sideff_type = Names.Id.t list
and opacity_guarantee =
| GuaranteesOpacity (** Only generates opaque terms at [Qed] *)
diff --git a/vernac/vernacstate.ml b/vernac/vernacstate.ml
index 61540024ef..c691dc8559 100644
--- a/vernac/vernacstate.ml
+++ b/vernac/vernacstate.ml
@@ -8,10 +8,30 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+module Parser = struct
+
+ type state = Pcoq.frozen_t
+
+ let init () = Pcoq.freeze ~marshallable:false
+
+ let cur_state () = Pcoq.freeze ~marshallable:false
+
+ let parse ps entry pa =
+ Pcoq.unfreeze ps;
+ Flags.with_option Flags.we_are_parsing (fun () ->
+ try Pcoq.Entry.parse entry pa
+ with e when CErrors.noncritical e ->
+ let (e, info) = CErrors.push e in
+ Exninfo.iraise (e, info))
+ ()
+
+end
+
type t = {
- system : States.state; (* summary + libstack *)
- proof : Proof_global.t; (* proof state *)
- shallow : bool (* is the state trimmed down (libstack) *)
+ parsing: Parser.state;
+ system : States.state; (* summary + libstack *)
+ proof : Proof_global.t; (* proof state *)
+ shallow : bool; (* is the state trimmed down (libstack) *)
}
let s_cache = ref None
@@ -37,11 +57,13 @@ let freeze_interp_state ~marshallable =
{ system = update_cache s_cache (States.freeze ~marshallable);
proof = update_cache s_proof (Proof_global.freeze ~marshallable);
shallow = false;
+ parsing = Parser.cur_state ();
}
-let unfreeze_interp_state { system; proof } =
+let unfreeze_interp_state { system; proof; parsing } =
do_if_not_cached s_cache States.unfreeze system;
- do_if_not_cached s_proof Proof_global.unfreeze proof
+ do_if_not_cached s_proof Proof_global.unfreeze proof;
+ Pcoq.unfreeze parsing
let make_shallow st =
let lib = States.lib_of_state st.system in
diff --git a/vernac/vernacstate.mli b/vernac/vernacstate.mli
index ed20cb935a..581c23386a 100644
--- a/vernac/vernacstate.mli
+++ b/vernac/vernacstate.mli
@@ -8,10 +8,21 @@
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
+module Parser : sig
+ type state
+
+ val init : unit -> state
+ val cur_state : unit -> state
+
+ val parse : state -> 'a Pcoq.Entry.t -> Pcoq.Parsable.t -> 'a
+
+end
+
type t = {
- system : States.state; (* summary + libstack *)
- proof : Proof_global.t; (* proof state *)
- shallow : bool (* is the state trimmed down (libstack) *)
+ parsing: Parser.state;
+ system : States.state; (* summary + libstack *)
+ proof : Proof_global.t; (* proof state *)
+ shallow : bool; (* is the state trimmed down (libstack) *)
}
val freeze_interp_state : marshallable:bool -> t